全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-15 6 分钟 ✍️ juanwangdev

Node.js 回调函数

回调函数是 Node.js 异步编程的基础,作为参数传入函数,在操作完成后被调用。

什么是回调函数

JavaScript
// 回调函数:作为参数传入,完成后调用
function fetchData(callback) {
  setTimeout(() => {
    callback('数据');
  }, 1000);
}

fetchData((data) => {
  console.log('收到:', data);
});

同步回调与异步回调

同步回调

JavaScript
// 同步执行,立即调用
const arr = [1, 2, 3];
arr.forEach((item) => {
  console.log(item); // 同步执行
});

异步回调

JavaScript
// 异步执行,稍后调用
setTimeout(() => {
  console.log('延迟执行'); // 异步执行
}, 1000);

Error-First 规范

Node.js 回调遵循"错误优先"原则:

JavaScript
// 回调函数第一个参数是错误对象
fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) {
    console.error('错误:', err.message);
    return;
  }
  console.log('数据:', data);
});

// 自定义异步函数
function asyncOperation(callback) {
  doSomething((result, error) => {
    if (error) {
      callback(error); // 错误作为第一个参数
    } else {
      callback(null, result); // 成功时第一个参数为 null
    }
  });
}

回调地狱问题

JavaScript
// 多层嵌套导致代码难以阅读
fs.readFile('file1.txt', 'utf8', (err1, data1) => {
  if (err1) throw err1;
  fs.readFile('file2.txt', 'utf8', (err2, data2) => {
    if (err2) throw err2;
    fs.readFile('file3.txt', 'utf8', (err3, data3) => {
      if (err3) throw err3;
      fs.writeFile('output.txt', data1 + data2 + data3, (err4) => {
        if (err4) throw err4;
        console.log('完成');
      });
    });
  });
});

解决回调地狱

拆分函数

JavaScript
function readFiles(callback) {
  fs.readFile('file1.txt', 'utf8', (err, data1) => {
    if (err) return callback(err);
    fs.readFile('file2.txt', 'utf8', (err, data2) => {
      if (err) return callback(err);
      fs.readFile('file3.txt', 'utf8', (err, data3) => {
        if (err) return callback(err);
        callback(null, data1 + data2 + data3);
      });
    });
  });
}

readFiles((err, result) => {
  if (err) console.error(err);
  else console.log(result);
});

使用 Promise

JavaScript
const fs = require('fs').promises;

async function readFiles() {
  const data1 = await fs.readFile('file1.txt', 'utf8');
  const data2 = await fs.readFile('file2.txt', 'utf8');
  const data3 = await fs.readFile('file3.txt', 'utf8');
  return data1 + data2 + data3;
}

readFiles().then(console.log).catch(console.error);

回调函数注意事项

JavaScript
// ❌ 错误:直接抛出异常会丢失
function badCallback() {
  setTimeout(() => {
    throw new Error('无法捕获');
  }, 1000);
}

// ✅ 正确:通过回调传递错误
function goodCallback(callback) {
  setTimeout(() => {
    callback(new Error('通过回调传递'));
  }, 1000);
}

goodCallback((err) => {
  if (err) console.error(err);
});

回调中的异常无法被外部 try-catch 捕获,必须通过回调传递错误。

要点总结

  • 回调函数在操作完成后被调用
  • Node.js 回调遵循 Error-First 规范(第一个参数为错误)
  • 多层嵌套导致回调地狱,代码难以维护
  • 使用 Promise 或拆分函数解决回调地狱
  • 回调中的异常无法被外部捕获

📝 发现内容有误?点击此处直接编辑

← 上一篇 Node.js 事件循环
下一篇 → Node.js EventEmitter 事件发射器
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库