Search K
Appearance
Appearance
📊 SEO元描述:2024年最新async/await并发控制教程,详解顺序执行vs并行执行、Promise.all()与async/await结合技巧。包含完整并发控制方案,适合JavaScript开发者掌握高性能异步编程。
核心关键词:async/await并发控制2024、JavaScript并行执行、Promise.all异步编程、异步并发控制、JavaScript性能优化
长尾关键词:async/await怎么并行执行、JavaScript异步并发控制技巧、Promise.all和async/await结合、异步编程性能优化、JavaScript并发编程最佳实践
通过本节async/await并发控制教程,你将系统性掌握:
为什么并发控制如此重要?这是高性能JavaScript应用开发的核心问题。合理的并发控制不仅能显著提升应用性能,还能改善用户体验,也是现代JavaScript异步编程的高级技能。
💡 核心原则:能并行的操作尽量并行,需要顺序的操作保持顺序,合理控制并发数量避免系统过载
理解顺序执行和并行执行的差异是掌握并发控制的基础。
// 🎉 顺序执行 vs 并行执行对比示例
// 模拟异步操作
function fetchData(id, delay = 1000) {
return new Promise(resolve => {
setTimeout(() => {
resolve({
id,
data: `数据${id}`,
timestamp: Date.now()
});
}, delay);
});
}
// 1. 顺序执行(Sequential Execution)
async function sequentialExecution() {
console.log('开始顺序执行...');
const startTime = Date.now();
const result1 = await fetchData(1, 1000);
console.log('第1个数据获取完成:', result1);
const result2 = await fetchData(2, 1000);
console.log('第2个数据获取完成:', result2);
const result3 = await fetchData(3, 1000);
console.log('第3个数据获取完成:', result3);
const endTime = Date.now();
console.log(`顺序执行总耗时: ${endTime - startTime}ms`); // 约3000ms
return [result1, result2, result3];
}
// 2. 并行执行(Parallel Execution)
async function parallelExecution() {
console.log('开始并行执行...');
const startTime = Date.now();
// 同时启动所有异步操作
const promise1 = fetchData(1, 1000);
const promise2 = fetchData(2, 1000);
const promise3 = fetchData(3, 1000);
// 等待所有操作完成
const [result1, result2, result3] = await Promise.all([
promise1,
promise2,
promise3
]);
const endTime = Date.now();
console.log(`并行执行总耗时: ${endTime - startTime}ms`); // 约1000ms
return [result1, result2, result3];
}
// 3. 混合执行模式(部分顺序,部分并行)
async function hybridExecution() {
console.log('开始混合执行...');
const startTime = Date.now();
// 第一阶段:并行获取基础数据
const [userData, configData] = await Promise.all([
fetchData('user', 800),
fetchData('config', 600)
]);
console.log('基础数据获取完成');
// 第二阶段:基于第一阶段结果,并行获取详细数据
const [userDetails, userPermissions] = await Promise.all([
fetchData(`user-details-${userData.id}`, 500),
fetchData(`user-permissions-${userData.id}`, 700)
]);
const endTime = Date.now();
console.log(`混合执行总耗时: ${endTime - startTime}ms`); // 约1300ms
return {
userData,
configData,
userDetails,
userPermissions
};
}
// 性能对比测试
async function performanceComparison() {
console.log('=== 性能对比测试 ===');
await sequentialExecution(); // ~3000ms
console.log('---');
await parallelExecution(); // ~1000ms
console.log('---');
await hybridExecution(); // ~1300ms
}Promise.all()是实现并行执行的核心工具,与async/await结合使用效果更佳。
// 🎉 Promise.all()与async/await结合的高级技巧
// 模拟不同类型的API调用
async function fetchUserProfile(userId) {
await new Promise(resolve => setTimeout(resolve, 800));
return { userId, name: `用户${userId}`, avatar: `avatar${userId}.jpg` };
}
async function fetchUserPosts(userId) {
await new Promise(resolve => setTimeout(resolve, 1200));
return [
{ id: 1, title: '第一篇文章', author: userId },
{ id: 2, title: '第二篇文章', author: userId }
];
}
async function fetchUserFollowers(userId) {
await new Promise(resolve => setTimeout(resolve, 600));
return [
{ id: 101, name: '粉丝1' },
{ id: 102, name: '粉丝2' }
];
}
// 1. 基础并行执行
async function loadUserDashboard(userId) {
try {
console.log('开始加载用户仪表板...');
const startTime = Date.now();
// 并行执行所有数据获取操作
const [profile, posts, followers] = await Promise.all([
fetchUserProfile(userId),
fetchUserPosts(userId),
fetchUserFollowers(userId)
]);
const endTime = Date.now();
console.log(`仪表板加载完成,耗时: ${endTime - startTime}ms`);
return {
profile,
posts,
followers,
loadTime: endTime - startTime
};
} catch (error) {
console.error('加载用户仪表板失败:', error);
throw error;
}
}
// 2. 带有容错的并行执行
async function loadUserDashboardWithFallback(userId) {
console.log('开始加载用户仪表板(带容错)...');
const startTime = Date.now();
// 使用Promise.allSettled处理部分失败的情况
const results = await Promise.allSettled([
fetchUserProfile(userId),
fetchUserPosts(userId),
fetchUserFollowers(userId)
]);
// 处理结果,提供默认值
const profile = results[0].status === 'fulfilled'
? results[0].value
: { userId, name: '未知用户', avatar: 'default.jpg' };
const posts = results[1].status === 'fulfilled'
? results[1].value
: [];
const followers = results[2].status === 'fulfilled'
? results[2].value
: [];
const endTime = Date.now();
console.log(`仪表板加载完成(带容错),耗时: ${endTime - startTime}ms`);
return {
profile,
posts,
followers,
loadTime: endTime - startTime,
errors: results.filter(r => r.status === 'rejected').map(r => r.reason)
};
}
// 3. 分批并行处理
async function processBatchData(dataList, batchSize = 3) {
console.log(`开始分批处理${dataList.length}条数据,批次大小: ${batchSize}`);
const results = [];
// 将数据分成批次
for (let i = 0; i < dataList.length; i += batchSize) {
const batch = dataList.slice(i, i + batchSize);
console.log(`处理第${Math.floor(i / batchSize) + 1}批数据...`);
// 并行处理当前批次
const batchResults = await Promise.all(
batch.map(async (item, index) => {
const actualIndex = i + index;
return await processItem(item, actualIndex);
})
);
results.push(...batchResults);
console.log(`第${Math.floor(i / batchSize) + 1}批处理完成`);
}
return results;
}
// 4. 带有超时控制的并行执行
async function loadDataWithTimeout(userId, timeout = 5000) {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('操作超时')), timeout);
});
try {
const result = await Promise.race([
Promise.all([
fetchUserProfile(userId),
fetchUserPosts(userId),
fetchUserFollowers(userId)
]),
timeoutPromise
]);
return {
success: true,
data: {
profile: result[0],
posts: result[1],
followers: result[2]
}
};
} catch (error) {
if (error.message === '操作超时') {
console.warn('数据加载超时,返回缓存数据');
return {
success: false,
error: '加载超时',
data: await getCachedUserData(userId)
};
}
throw error;
}
}
// 5. 动态并发控制
class ConcurrencyController {
constructor(maxConcurrency = 3) {
this.maxConcurrency = maxConcurrency;
this.running = 0;
this.queue = [];
}
async execute(asyncFunction) {
return new Promise((resolve, reject) => {
this.queue.push({
asyncFunction,
resolve,
reject
});
this.process();
});
}
async process() {
if (this.running >= this.maxConcurrency || this.queue.length === 0) {
return;
}
this.running++;
const { asyncFunction, resolve, reject } = this.queue.shift();
try {
const result = await asyncFunction();
resolve(result);
} catch (error) {
reject(error);
} finally {
this.running--;
this.process(); // 处理队列中的下一个任务
}
}
}
// 使用并发控制器
async function processLargeDataset(dataList) {
const controller = new ConcurrencyController(3); // 最大并发数为3
const promises = dataList.map(data =>
controller.execute(() => processItem(data))
);
return await Promise.all(promises);
}Promise.all()使用技巧总结:
通过本节async/await并发控制教程的学习,你已经掌握:
A: 当操作之间相互独立时使用并行执行以提升性能;当后续操作依赖前面操作的结果时使用顺序执行。可以通过混合模式在复杂场景中获得最佳性能。
A: Promise.all()在任一Promise失败时立即失败;Promise.allSettled()等待所有Promise完成(无论成功或失败)并返回所有结果。后者适合需要容错的场景。
A: 可以使用分批处理、队列机制或专门的并发控制器来限制同时执行的异步操作数量。根据系统资源和API限制设置合理的并发数。
A: 不一定。如果操作之间有依赖关系,强制并行可能导致错误。另外,过多的并发可能导致资源竞争,反而降低性能。需要根据具体场景选择。
A: 可以使用Promise.allSettled()获取所有结果(包括错误),或者在每个异步操作中单独处理错误。重要的是要有合适的降级策略。
"掌握async/await的并发控制是提升JavaScript应用性能的关键技能。通过合理的并发策略,不仅能显著提升代码执行效率,更能为用户提供更流畅的体验。记住:并发不是越多越好,而是要找到最适合的平衡点!"