文章中英模式
布魯斯前端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));