湖州市文章资讯

Node.js 回调函数的基本用法

2026-03-31 09:45:02 浏览次数:2
详细信息

Node.js 回调函数的基本用法是通过将函数作为参数传递给异步操作,在操作完成后执行该函数。以下是详细说明:

1. 回调函数的基本概念

回调函数是 Node.js 处理异步操作的核心机制,遵循 "error-first" 约定。

// 基本格式
function callback(error, result) {
  if (error) {
    // 处理错误
    console.error('错误:', error);
    return;
  }
  // 处理成功结果
  console.log('结果:', result);
}

2. 实际应用示例

文件读取示例

const fs = require('fs');

// 读取文件(异步操作)
fs.readFile('example.txt', 'utf8', (err, data) => {
  if (err) {
    console.error('读取文件出错:', err);
    return;
  }
  console.log('文件内容:', data);
});

自定义异步函数

// 创建使用回调的自定义函数
function getUserData(userId, callback) {
  setTimeout(() => {
    if (userId > 0) {
      callback(null, {
        id: userId,
        name: '张三',
        email: 'zhangsan@example.com'
      });
    } else {
      callback(new Error('用户ID无效'));
    }
  }, 1000);
}

// 使用自定义函数
getUserData(123, (err, user) => {
  if (err) {
    console.error('获取用户数据失败:', err.message);
    return;
  }
  console.log('用户数据:', user);
});

3. 回调金字塔(回调地狱)及解决方法

回调嵌套问题

// 回调地狱示例
fs.readFile('file1.txt', 'utf8', (err, data1) => {
  if (err) return console.error(err);

  fs.readFile('file2.txt', 'utf8', (err, data2) => {
    if (err) return console.error(err);

    fs.writeFile('result.txt', data1 + data2, (err) => {
      if (err) return console.error(err);
      console.log('操作完成');
    });
  });
});

解决方案:Promise 或 Async/Await

// 使用 Promise
const fs = require('fs').promises;

async function processFiles() {
  try {
    const data1 = await fs.readFile('file1.txt', 'utf8');
    const data2 = await fs.readFile('file2.txt', 'utf8');
    await fs.writeFile('result.txt', data1 + data2);
    console.log('操作完成');
  } catch (err) {
    console.error('出错:', err);
  }
}

4. 事件驱动示例

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();

// 设置事件监听器(一种特殊的回调)
myEmitter.on('event', (arg1, arg2) => {
  console.log('事件触发,参数:', arg1, arg2);
});

// 触发事件
myEmitter.emit('event', '参数1', '参数2');

5. 实用技巧

回调函数柯里化

function createLogger(prefix) {
  return function(err, result) {
    const timestamp = new Date().toISOString();
    if (err) {
      console.error(`[${timestamp}] ${prefix} 错误:`, err.message);
    } else {
      console.log(`[${timestamp}] ${prefix} 结果:`, result);
    }
  };
}

fs.readFile('data.txt', 'utf8', createLogger('文件读取'));

回调函数封装

function promisify(fn) {
  return function(...args) {
    return new Promise((resolve, reject) => {
      fn(...args, (err, result) => {
        if (err) reject(err);
        else resolve(result);
      });
    });
  };
}

// 将回调函数转换为 Promise
const readFileAsync = promisify(fs.readFile);
readFileAsync('file.txt', 'utf8')
  .then(data => console.log(data))
  .catch(err => console.error(err));

关键要点

错误优先:回调函数的第一个参数总是错误对象 异步执行:回调函数在事件循环的后续阶段执行 避免阻塞:回调函数中不要执行同步阻塞操作 现代替代方案:对于新项目,推荐使用 Promise 或 async/await

虽然回调函数是 Node.js 的基础,但在现代开发中,通常建议使用 Promise 或 async/await 语法来处理异步操作,以提高代码的可读性和可维护性。

相关推荐