文章中英模式
布鲁斯前端JS面试题目 - 实现执行异步任务
学习如何实现 JavaScript 中的异步任务执行,掌握批量处理、控制并发数、执行顺序管理等技巧,提升前端处理复杂流程的能力。
文章中英模式
懒得看文章?那就来看视频吧
异步任务执行概述
在前端开发中,我们经常需要处理多个异步操作,如 API 请求、文件读取等。有效管理这些异步任务的执行顺序、并发数量和错误处理是一个常见的面试题目。
异步任务执行的常见场景
- 1. 串行执行:按顺序一个接一个地执行任务
- 2. 并行执行:同时执行多个任务
- 3. 并发控制:限制同时执行的任务数量
- 4. 任务调度:根据优先级或依赖关系安排任务执行顺序
- 5. 批量处理:将多个任务分批执行
基本串行执行异步任务
串行执行是最简单的异步任务执行方式,确保任务按照指定顺序一个接一个地执行。下面是一个基本实现:
async function executeAsyncTasks(tasks) {
if (tasks.length === 0) {
return;
}
const task = tasks.shift();
const result = await task();
console.log(result);
await executeAsyncTasks(tasks);
}
// 使用範例
const tasks = [
() => Promise.resolve('Task 1 completed'),
() => Promise.resolve('Task 2 completed'),
() => Promise.resolve('Task 3 completed')
];
executeAsyncTasks([...tasks]);
// 依次輸出:
// Task 1 completed
// Task 2 completed
// Task 3 completed
这个实现使用了递归方式一个接一个地执行任务。每次执行一个任务,等待它完成后再执行下一个任务。
基本实现的改进版
async function executeAsyncTasks(tasks) {
const results = [];
for (const task of tasks) {
try {
const result = await task();
results.push(result);
} catch (error) {
results.push({ error });
}
}
return results;
}
// 使用範例
const tasks = [
() => Promise.resolve('Success 1'),
() => Promise.reject(new Error('Failed')),
() => Promise.resolve('Success 3')
];
executeAsyncTasks(tasks)
.then(results => console.log(results))
.catch(error => console.error(error));
// 輸出: ['Success 1', { error: Error('Failed') }, 'Success 3']
这个改进版本收集了所有任务的结果,并处理了可能的错误,使整个过程更加健壮。
实际应用场景
以下是两个异步任务执行的实际应用示例:
1. 批量上传文件
async function uploadFiles(files, concurrency = 3) {
const uploadFile = async (file) => {
// 创建表单数据
const formData = new FormData();
formData.append('file', file);
// 模拟上传过程
const response = await fetch('/api/upload', {
method: 'POST',
body: formData
});
return await response.json();
};
// 创建所有上传任务
const uploadTasks = files.map(file => () => uploadFile(file));
// 使用并发控制上传
return executeAsyncTasks(uploadTasks);
}
// 使用示例
const fileList = [file1, file2, file3];
uploadFiles(fileList)
.then(results => console.log('Upload complete:', results))
.catch(error => console.error('Upload failed:', error));
2. API 数据依赖关系处理
async function fetchUserData(userId) {
// 步骤 1: 获取用户基本信息
const userInfo = await fetch(`/api/user/${userId}`)
.then(res => res.json());
// 步骤 2: 基于用户信息获取相关数据
const tasks = [
() => fetch(`/api/posts?userId=${userId}`).then(res => res.json()),
() => fetch(`/api/followers?userId=${userId}`).then(res => res.json())
];
// 依序执行任务
const [posts, followers] = await executeAsyncTasks(tasks);
// 返回整合后的数据
return {
user: userInfo,
posts,
followers
};
}
// 使用示例
fetchUserData('user123')
.then(data => {
displayUserProfile(data.user);
displayUserPosts(data.posts);
displayFollowers(data.followers);
})
.catch(error => console.error('Failed to fetch user data:', error));