# JavaScript异步编程:Promise与async/await深度解析
## Promise核心机制
Promise是JavaScript异步编程的基石,它代表一个异步操作的最终完成或失败及其结果值。Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
### Promise创建与基本使用
```javascript
// Promise构造函数接受一个执行器函数
const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
const success = Math.random() > 0.5;
if (success) {
resolve('操作成功');
} else {
reject(new Error('操作失败'));
}
}, 1000);
});
// 使用then、catch处理结果
promise
.then(result => {
console.log(result);
})
.catch(error => {
console.error(error.message);
});
```
### Promise链式调用
Promise的then方法返回一个新的Promise,这使得链式调用成为可能:
```javascript
function fetchUserData(userId) {
return new Promise((resolve) => {
setTimeout(() => resolve({ id: userId, name: '张三' }), 500);
});
}
function fetchUserPosts(userId) {
return new Promise((resolve) => {
setTimeout(() => resolve(['文章1', '文章2']), 300);
});
}
fetchUserData(1)
.then(user => {
console.log('获取用户:', user);
return fetchUserPosts(user.id);
})
.then(posts => {
console.log('获取文章:', posts);
})
.catch(error => {
console.error('发生错误:', error);
});
```
### Promise静态方法
Promise提供了多个实用的静态方法:
```javascript
// Promise.all - 所有Promise都成功时返回结果数组
Promise.all([promise1, promise2, promise3])
.then(results => {
console.log('所有操作完成:', results);
})
.catch(error => {
console.error('有一个操作失败:', error);
});
// Promise.race - 第一个完成(成功或失败)的Promise
Promise.race([promise1, promise2])
.then(result => {
console.log('第一个完成的结果:', result);
});
// Promise.allSettled - 所有Promise都完成(无论成功失败)
Promise.allSettled([promise1, promise2])
.then(results => {
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log('成功:', result.value);
} else {
console.log('失败:', result.reason);
}
});
});
```
## async/await语法糖
async/await是基于Promise的语法糖,让异步代码看起来像同步代码,提高了代码的可读性。
### 基本用法
```javascript
// async函数总是返回Promise
async function getUserInfo(userId) {
try {
const user = await fetchUserData(userId);
const posts = await fetchUserPosts(user.id);
return { user, posts };
} catch (error) {
console.error('获取用户信息失败:', error);
throw error;
}
}
// 使用async函数
getUserInfo(1)
.then(info => {
console.log('用户信息:', info);
});
```
### 错误处理策略
```javascript
// 方法1: try-catch块
async function processData() {
try {
const data = await fetchData();
const processed = await process(data);
return processed;
} catch (error) {
console.error('处理失败:', error);
return null;
}
}
// 方法2: 在调用处使用catch
async function riskyOperation() {
const result = await potentiallyFailingOperation();
return result;
}
riskyOperation().catch(error => {
console.error('操作失败:', error);
});
```
### 并行执行优化
```javascript
// 错误的串行执行 - 耗时较长
async function slowFetch() {
const user = await fetchUser();
const posts = await fetchPosts();
const comments = await fetchComments();
return { user, posts, comments };
}
// 正确的并行执行 - 效率更高
async function fastFetch() {
const [user, posts, comments] = await Promise.all([
fetchUser(),
fetchPosts(),
fetchComments()
]);
return { user, posts, comments };
}
```
## 高级模式与最佳实践
### 重试机制
```javascript
async function retryOperation(operation, maxRetries = 3, delay = 1000) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
if (attempt === maxRetries) throw error;
console.log(`尝试 ${attempt} 失败,${delay}ms后重试`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
```
### 超时控制
```javascript
function withTimeout(promise, timeoutMs) {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('操作超时')), timeoutMs);
});
return Promise.race([promise, timeoutPromise]);
}
// 使用示例
async function fetchWithTimeout() {
try {
const result = await withTimeout(fetchData(), 5000);
return result;
} catch (error) {
if (error.message === '操作超时') {
console.log('请求超时');
} else {
console.log('其他错误:', error);
}
}
}
```
### 批量处理
```javascript
async function processInBatches(items, batchSize, processor) {
const results = [];
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
const batchPromises = batch.map(item => processor(item));
const batchResults = await Promise.all(batchPromises);
results.push(...batchResults);
// 可选:批次间延迟
await new Promise(resolve => setTimeout(resolve, 100));
}
return results;
}
```
## 性能考量与陷阱
### 常见陷阱
1. 忘记await
```javascript
// 错误:忘记await导致Promise未被正确处理
async function incorrect() {
const result = someAsyncFunction(); // 缺少await
console.log(result); // 输出: Promise { }
}
// 正确
async function correct() {
const result = await someAsyncFunction();
console.log(result); // 输出实际结果
}
```
2. 不必要的串行化
```javascript
// 低效的串行执行
async function inefficient() {
const a = await taskA();
const b = await taskB(); // 等待taskA完成后才开始
return a + b;
}
// 高效的并行执行
async function efficient() {
const [a, b] = await Promise.all([taskA(), taskB()]);
return a + b;
}
```
### 内存管理
在大量异步操作时需要注意内存使用:
```javascript
// 可能的内存泄漏
async function processLargeArray(array) {
const promises = array.map(item => processItem(item));
return await Promise.all(promises); // 一次性处理所有项目
}
// 改进的分批处理
async function processLargeArraySafely(array, batchSize = 100) {
const results = [];
for (let i = 0; i < array.length; i += batchSize) {
const batch = array.slice(i, i + batchSize);
const batchResults = await Promise.all(
batch.map(item => processItem(item))
);
results.push(...batchResults);
}
return results;
}
```
## 实际应用场景
### API请求管理
```javascript
class ApiClient {
constructor(baseURL) {
this.baseURL = baseURL;
}
async request(endpoint, options = {}) {
const url = `${this.baseURL}${endpoint}`;
try {
const response = await fetch(url, {
headers: {
'Content-Type': 'application/json',
...options.headers,
},
...options,
});
if (!response.ok) {
throw new Error(`HTTP错误: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error(`API请求失败: ${error.message}`);
throw error;
}
}
async get(endpoint) {
return this.request(endpoint);
}
async post(endpoint, data) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(data),
});
}
}
```
### 复杂工作流程
```javascript
async function complexWorkflow() {
// 阶段1: 数据准备(并行执行)
const [userData, config] = await Promise.all([
fetchUserData(),
fetchConfig(),
]);
// 阶段2: 数据处理(依赖阶段1结果)
const processedData = await processData(userData, config);
// 阶段3: 验证和保存(顺序执行但内部可并行)
const validationResult = await validateData(processedData);
if (!validationResult.valid) {
throw new Error('数据验证失败');
}
const [saveResult, auditLog] = await Promise.all([
saveData(processedData),
createAuditLog(processedData),
]);
return { saveResult, auditLog };
}
```
Promise和async/await的组合为JavaScript异步编程提供了强大而优雅的解决方案。理解它们的内部机制、掌握最佳实践并避免常见陷阱,对于构建高效可靠的异步应用程序至关重要。
936

被折叠的 条评论
为什么被折叠?



