面试题答案
一键面试function asyncTask(url) {
return new Promise((resolve, reject) => {
// 模拟异步操作,这里以fetch为例
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => resolve(data))
.catch(error => reject(error));
});
}
async function executeTasks(tasks, concurrency) {
const results = [];
const runningTasks = [];
for (let i = 0; i < concurrency; i++) {
const task = tasks.shift();
if (task) {
const promise = asyncTask(task);
runningTasks.push(promise);
promise
.then(result => {
results.push(result);
const nextTask = tasks.shift();
if (nextTask) {
const newPromise = asyncTask(nextTask);
runningTasks.push(newPromise);
newPromise
.then(nextResult => results.push(nextResult))
.catch(error => results.push({ error }))
.finally(() => runningTasks.splice(runningTasks.indexOf(newPromise), 1));
}
})
.catch(error => results.push({ error }))
.finally(() => runningTasks.splice(runningTasks.indexOf(promise), 1));
}
}
while (runningTasks.length > 0) {
await Promise.race(runningTasks);
}
return results;
}
// 示例任务数组
const taskUrls = [
'url1',
'url2',
'url3',
'url4',
'url5',
'url6',
'url7',
'url8',
'url9',
'url10'
];
executeTasks(taskUrls, 5)
.then(finalResults => {
console.log(finalResults);
})
.catch(error => {
console.error('Overall error:', error);
});
asyncTask
函数:- 此函数接受一个
url
参数,返回一个Promise
。 - 这里通过
fetch
模拟异步获取数据的操作,处理响应并返回解析后的数据,如果请求失败则reject
。
- 此函数接受一个
executeTasks
函数:tasks
参数是包含所有任务(这里是URL)的数组,concurrency
参数表示最大并发数。results
数组用于存储所有任务的执行结果,runningTasks
数组用于跟踪当前正在运行的任务。- 首先,循环启动
concurrency
数量的任务,并将其添加到runningTasks
数组中。每个任务完成后,从tasks
数组中取出下一个任务并启动,同时处理任务执行过程中的成功和失败情况。 - 使用
while
循环和Promise.race
等待所有正在运行的任务完成,Promise.race
会在任何一个Promise
完成(无论成功或失败)时返回。
- 示例使用:
- 定义一个包含多个URL的
taskUrls
数组。 - 调用
executeTasks
函数,传入taskUrls
和最大并发数5
,并处理最终的结果或错误。
- 定义一个包含多个URL的
这样就实现了在最大并发数限制下,顺序执行所有异步任务并处理错误的功能。