第八章:异步编程与Promise
8.1 回调函数
基础回调
// 同步函数
function syncAdd(a, b) {
return a + b;
}
// 异步回调函数
function asyncAdd(a, b, callback) {
setTimeout(() => {
const result = a + b;
callback(result);
}, 1000);
}
// 使用
asyncAdd(5, 3, (result) => {
console.log('结果:', result); // 8
});
console.log('这行先执行');
回调地狱
// 嵌套回调(回调地狱)
getUserData(userId, (user) => {
getOrders(user.id, (orders) => {
getOrderDetails(orders[0].id, (details) => {
getProductInfo(details.productId, (product) => {
console.log(product);
});
});
});
});
8.2 Promise
基础Promise
// 创建Promise
const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
const success = true;
if (success) {
resolve('操作成功');
} else {
reject('操作失败');
}
}, 1000);
});
// 使用Promise
promise
.then(result => {
console.log(result); // 操作成功
})
.catch(error => {
console.error(error);
})
.finally(() => {
console.log('无论成功失败都执行');
});
Promise链式调用
function fetchUser(userId) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ id: userId, name: '张三' });
}, 500);
});
}
function fetchOrders(userId) {
return new Promise((resolve) => {
setTimeout(() => {
resolve([
{ id: 1, userId: userId, total: 100 },
{ id: 2, userId: userId, total: 200 }
]);
}, 500);
});
}
// 链式调用
fetchUser(1)
.then(user => {
console.log('用户:', user);
return fetchOrders(user.id);
})
.then(orders => {
console.log('订单:', orders);
return orders[0];
})
.then(order => {
console.log('第一个订单:', order);
})
.catch(err => {
console.error('错误:', err);
});
Promise静态方法
// Promise.resolve
const resolved = Promise.resolve(42);
resolved.then(value => console.log(value)); // 42
// Promise.reject
const rejected = Promise.reject(new Error('出错了'));
rejected.catch(err => console.error(err));
// Promise.all - 等待所有Promise完成
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3])
.then(values => {
console.log(values); // [1, 2, 3]
});
// Promise.race - 返回最快的Promise
const fast = new Promise(resolve => setTimeout(() => resolve('fast'), 100));
const slow = new Promise(resolve => setTimeout(() => resolve('slow'), 500));
Promise.race([fast, slow])
.then(winner => {
console.log(winner); // fast
});
// Promise.allSettled - 等待所有完成(无论成功失败)
const promises = [
Promise.resolve('success'),
Promise.reject('error'),
Promise.resolve('another success')
];
Promise.allSettled(promises)
.then(results => {
console.log(results);
// [
// { status: 'fulfilled', value: 'success' },
// { status: 'rejected', reason: 'error' },
// { status: 'fulfilled', value: 'another success' }
// ]
});
// Promise.any - 返回第一个成功的
const promises2 = [
Promise.reject('error1'),
Promise.resolve('success'),
Promise.reject('error2')
];
Promise.any(promises2)
.then(firstSuccess => {
console.log(firstSuccess); // success
});
8.3 async/await
基础用法
// async函数返回Promise
async function fetchData() {
return '数据';
}
// 等同于
function fetchData2() {
return Promise.resolve('数据');
}
// await等待Promise完成
async function main() {
try {
const result = await fetchData();
console.log(result); // 数据
} catch (err) {
console.error(err);
}
}
main();
实际应用
const fs = require('fs').promises;
// 读取多个文件
async function readFiles() {
try {
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];
} catch (err) {
console.error('读取失败:', err);
throw err;
}
}
// 并行执行
async function parallelFetch() {
const [users, posts, comments] = await Promise.all([
fetch('/api/users'),
fetch('/api/posts'),
fetch('/api/comments')
]);
return { users, posts, comments };
}
// 串行执行
async function sequentialFetch() {
const user = await fetchUser(1);
const orders = await fetchOrders(user.id);
const details = await fetchOrderDetails(orders[0].id);
return details;
}
// 循环中使用await
async function processItems(items) {
const results = [];
for (const item of items) {
const result = await processItem(item);
results.push(result);
}
return results;
}
// 带限制的并发
async function limitedConcurrency(items, limit) {
const results = [];
const executing = [];
for (const item of items) {
const promise = processItem(item).then(result => {
results.push(result);
return result;
});
executing.push(promise);
if (executing.length >= limit) {
await Promise.race(executing);
executing.splice(executing.indexOf(promise), 1);
}
}
await Promise.all(executing);
return results;
}
8.4 EventEmitter与异步
const EventEmitter = require('events');
class AsyncEmitter extends EventEmitter {
async doSomething() {
this.emit('start');
try {
const result = await someAsyncOperation();
this.emit('success', result);
return result;
} catch (err) {
this.emit('error', err);
throw err;
}
}
}
const emitter = new AsyncEmitter();
emitter.on('start', () => {
console.log('开始执行');
});
emitter.on('success', (result) => {
console.log('执行成功:', result);
});
emitter.on('error', (err) => {
console.error('执行失败:', err);
});
emitter.doSomething();
8.5 错误处理
// try-catch捕获异步错误
async function safeOperation() {
try {
const result = await riskyOperation();
return result;
} catch (err) {
console.error('操作失败:', err);
return null;
}
}
// 多个catch
async function multipleOperations() {
try {
const a = await operationA();
const b = await operationB(a);
const c = await operationC(b);
return c;
} catch (err) {
if (err.code === 'ENOENT') {
console.error('文件不存在');
} else if (err.code === 'ECONNREFUSED') {
console.error('连接被拒绝');
} else {
console.error('未知错误:', err);
}
throw err;
}
}
// Promise错误处理
function promiseError() {
return new Promise((resolve, reject) => {
// 处理同步错误
try {
const result = someSyncOperation();
resolve(result);
} catch (err) {
reject(err);
}
});
}
// 全局错误处理
process.on('unhandledRejection', (reason, promise) => {
console.error('未处理的Promise拒绝:', reason);
});
process.on('uncaughtException', (err) => {
console.error('未捕获的异常:', err);
process.exit(1);
});