发布日期:2024年1月 | 作者:JavaScript技术专家
异步编程的演进与重要性
在现代Web开发中,异步编程已成为处理I/O操作、网络请求和用户交互的核心技术。从最初的回调函数到Promise,再到async/await,JavaScript的异步处理能力不断进化,为开发者提供了更优雅的解决方案。
一、Promise基础与核心概念
Promise的三种状态
- pending:初始状态,既不是成功也不是失败
- fulfilled:操作成功完成
- rejected:操作失败
基本Promise创建
// 创建Promise实例
const fetchUserData = new Promise((resolve, reject) => {
setTimeout(() => {
const success = Math.random() > 0.3;
if (success) {
resolve({ id: 1, name: '张三', email: 'zhangsan@example.com' });
} else {
reject(new Error('数据获取失败'));
}
}, 1000);
});
// 使用Promise
fetchUserData
.then(user => console.log('用户数据:', user))
.catch(error => console.error('错误:', error.message));
二、Promise链式调用高级模式
1. 顺序执行模式
function getUserProfile(userId) {
return fetch(`/api/users/${userId}`)
.then(response => {
if (!response.ok) throw new Error('用户不存在');
return response.json();
})
.then(user => {
// 获取用户详细信息后,再获取其订单
return fetch(`/api/orders?userId=${user.id}`);
})
.then(ordersResponse => ordersResponse.json())
.then(orders => {
// 组合用户信息和订单数据
return { user: user, orders: orders };
});
}
// 使用示例
getUserProfile(123)
.then(profile => {
console.log('用户档案:', profile);
})
.catch(error => {
console.error('获取用户档案失败:', error);
});
2. 条件链式调用
function processPayment(order, paymentMethod) {
return validateOrder(order)
.then(validatedOrder => {
if (paymentMethod === 'creditCard') {
return processCreditCardPayment(validatedOrder);
} else if (paymentMethod === 'paypal') {
return processPayPalPayment(validatedOrder);
} else {
throw new Error('不支持的支付方式');
}
})
.then(paymentResult => {
// 支付成功后更新订单状态
return updateOrderStatus(order.id, 'paid');
});
}
三、精细化错误处理策略
1. 分类错误处理
class ApiError extends Error {
constructor(message, statusCode) {
super(message);
this.name = 'ApiError';
this.statusCode = statusCode;
}
}
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}
function createUser(userData) {
return validateUserData(userData)
.then(validatedData => {
return fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(validatedData)
});
})
.then(response => {
if (!response.ok) {
throw new ApiError('API请求失败', response.status);
}
return response.json();
})
.catch(error => {
if (error instanceof ValidationError) {
// 处理验证错误
console.warn(`验证失败: ${error.field} - ${error.message}`);
throw error;
} else if (error instanceof ApiError) {
// 处理API错误
console.error(`API错误 ${error.statusCode}: ${error.message}`);
throw error;
} else {
// 处理未知错误
console.error('未知错误:', error);
throw new Error('创建用户失败');
}
});
}
2. 错误恢复机制
function fetchWithRetry(url, options = {}, maxRetries = 3) {
return new Promise((resolve, reject) => {
const attempt = (retryCount) => {
fetch(url, options)
.then(response => {
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
})
.then(resolve)
.catch(error => {
if (retryCount attempt(retryCount + 1), 1000 * Math.pow(2, retryCount));
} else {
reject(new Error(`请求失败,已重试${maxRetries}次: ${error.message}`));
}
});
};
attempt(0);
});
}
四、并行执行与性能优化
1. Promise.all 并行处理
async function loadDashboardData(userId) {
try {
const [user, orders, notifications, preferences] = await Promise.all([
fetchUser(userId),
fetchUserOrders(userId),
fetchUserNotifications(userId),
fetchUserPreferences(userId)
]);
return {
user,
orders,
notifications,
preferences
};
} catch (error) {
console.error('加载仪表板数据失败:', error);
throw error;
}
}
2. Promise.allSettled 容错处理
async function batchProcessUsers(userIds) {
const promises = userIds.map(userId =>
updateUserProfile(userId).catch(error => ({
userId,
status: 'failed',
error: error.message
}))
);
const results = await Promise.allSettled(promises);
const successful = results.filter(result =>
result.status === 'fulfilled' && result.value.status !== 'failed'
);
const failed = results.filter(result =>
result.status === 'rejected' || result.value.status === 'failed'
);
return {
total: results.length,
successful: successful.length,
failed: failed.length,
failures: failed.map(f => f.reason || f.value)
};
}
3. Promise.race 超时控制
function fetchWithTimeout(url, timeout = 5000) {
const fetchPromise = fetch(url);
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('请求超时')), timeout);
});
return Promise.race([fetchPromise, timeoutPromise]);
}
五、真实场景:电商订单处理系统
class OrderProcessor {
constructor() {
this.steps = [
'validateOrder',
'checkInventory',
'processPayment',
'updateInventory',
'sendConfirmation'
];
}
async processOrder(order) {
let currentOrder = { ...order };
for (const step of this.steps) {
try {
console.log(`执行步骤: ${step}`);
currentOrder = await this[step](currentOrder);
// 记录步骤完成状态
currentOrder.processingSteps = currentOrder.processingSteps || [];
currentOrder.processingSteps.push({
step,
status: 'completed',
timestamp: new Date().toISOString()
});
} catch (error) {
console.error(`步骤 ${step} 执行失败:`, error);
// 记录失败状态
currentOrder.processingSteps.push({
step,
status: 'failed',
error: error.message,
timestamp: new Date().toISOString()
});
// 执行补偿操作
await this.compensate(currentOrder, step);
throw new Error(`订单处理失败于步骤: ${step}`);
}
}
return currentOrder;
}
async validateOrder(order) {
if (!order.items || order.items.length === 0) {
throw new Error('订单中没有商品');
}
if (!order.customerId) {
throw new Error('缺少客户信息');
}
return order;
}
async checkInventory(order) {
const inventoryChecks = order.items.map(item =>
this.checkItemStock(item.productId, item.quantity)
);
await Promise.all(inventoryChecks);
return order;
}
async checkItemStock(productId, quantity) {
const stock = await fetch(`/api/inventory/${productId}`)
.then(res => res.json());
if (stock.available this.refundPayment(order.paymentId),
'updateInventory': () => this.restoreInventory(order.items)
};
if (compensationActions[failedStep]) {
await compensationActions[failedStep]();
}
}
}
// 使用示例
const processor = new OrderProcessor();
const order = {
id: 'ORD-001',
customerId: 'CUST-123',
items: [
{ productId: 'PROD-1', quantity: 2, price: 25.00 },
{ productId: 'PROD-2', quantity: 1, price: 15.00 }
],
total: 65.00,
paymentMethod: 'creditCard'
};
processor.processOrder(order)
.then(processedOrder => {
console.log('订单处理成功:', processedOrder);
})
.catch(error => {
console.error('订单处理失败:', error.message);
});
六、Promise最佳实践总结
代码质量要点
- 始终返回Promise:在then回调中返回新的Promise或值
- 避免Promise嵌套:使用链式调用替代深层嵌套
- 合理使用async/await:在复杂逻辑中使用async/await提高可读性
- 统一错误处理:在链的末尾使用catch处理所有错误
性能优化建议
- 使用Promise.all进行独立的并行操作
- 合理设置超时时间,避免长时间等待
- 实现重试机制处理临时性失败
- 使用Promise.allSettled处理部分失败场景
可维护性技巧
- 为不同的错误类型创建自定义Error类
- 使用清晰的函数名和变量名
- 添加适当的日志记录
- 实现完整的补偿机制

