Node.js基于事件循环和非阻塞I/O模型,其异步编程是实现高性能的关键。以下是三种主流异步编程方式的实现原理和代码示例。
回调函数模式
回调函数是Node.js最基础的异步处理方式,通过将函数作为参数传递实现异步控制流。fs模块的经典示例展示了这种模式:
const fs = require('fs');
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log('文件内容:', data);
});
这种模式会产生回调地狱问题,多层嵌套会降低代码可读性。错误处理必须在每个回调中单独进行,且无法使用try-catch捕获异步错误。
Promise对象
Promise通过链式调用解决了回调嵌套问题。使用util.promisify可以将回调式API转换为Promise:
const fs = require('fs');
const util = require('util');
const readFile = util.promisify(fs.readFile);
readFile('example.txt', 'utf8')
.then(data => console.log('文件内容:', data))
.catch(err => console.error('读取失败:', err));
Promise.all可以并行处理多个异步操作:
Promise.all([
readFile('file1.txt'),
readFile('file2.txt')
]).then(([data1, data2]) => {
console.log('合并结果:', data1 + data2);
});
async/await语法
async/await是基于Promise的语法糖,使异步代码看起来像同步代码:
async function processFiles() {
try {
const data1 = await readFile('file1.txt');
const data2 = await readFile('file2.txt');
console.log('处理结果:', data1 + data2);
} catch (err) {
console.error('处理失败:', err);
}
}
processFiles();
await只能在async函数中使用,错误处理可以通过try-catch实现。并行执行需要结合Promise.all:
async function parallelTasks() {
const [res1, res2] = await Promise.all([
fetchAPI('/endpoint1'),
fetchAPI('/endpoint2')
]);
return { res1, res2 };
}
事件驱动模式
EventEmitter类实现了观察者模式,适用于事件驱动的异步场景:
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (arg) => {
console.log('事件触发:', arg);
});
myEmitter.emit('event', '参数值');
性能优化建议
避免在热点路径上创建新Promise实例,高频事件处理应考虑使用setImmediate进行任务分解。对于CPU密集型任务,建议使用worker_threads模块创建独立线程。
错误处理策略
全局错误处理可以通过process对象的unhandledRejection事件:
process.on('unhandledRejection', (reason) => {
console.error('未处理的Promise拒绝:', reason);
});
async函数中应始终使用try-catch包裹await操作,Promise链中应包含catch处理。对于关键业务逻辑,建议实现重试机制和超时控制。
评论前必须登录!
注册