我正在尝试构建一个自动重试下载的下载器。基本上,一个任务队列会重试任务一定次数。我首先尝试使用 Promise.all() ,但使用“技巧”来规避“第一次拒绝失败”described here没有帮助(并且是该线程下面进一步描述的反模式)
所以我得到了一个可以工作的版本,它似乎在某种程度上满足了我的要求。至少它打印的结果是正确的。但它仍然抛出几个未捕获的异常测试X
错误/警告,我不知道该怎么办。
代码:
asd = async () => {
// Function simulating tasks which might fail.
function wait(ms, data) {
return new Promise( (resolve, reject) => setTimeout(() => {
if (Math.random() > 0.5){
resolve(data);
} else {
reject(data);
}
}, ms) );
}
let tasks = [];
const results = [];
// start the tasks
for ( let i = 0; i < 20; i++) {
const prom = wait(100 * i, 'test ' + i);
tasks.push([i, prom]);
}
// collect results and handle retries.
for ( let tries = 0; tries < 10; tries++){
failedTasks = [];
for ( let i = 0; i < tasks.length; i++) {
const task_idx = tasks[i][0];
// Wait for the task and check whether they failed or not.
// Any pointers on how to improve the readability of the next 6 lines appreciated.
await tasks[i][1].then(result => {
results.push([task_idx, result])
}).catch(err => {
const prom = wait(100 * task_idx, 'test ' + task_idx);
failedTasks.push([task_idx, prom])
});
}
// Retry the tasks which failed.
if (failedTasks.length === 0){
break;
} else {
tasks = failedTasks;
}
console.log('try ', tries);
}
console.log(results);
}
最后,results
数组包含(除非任务失败 10 次)所有结果。但仍然未捕获的异常
到处乱飞。
由于并非所有被拒绝的 promise 都会导致未捕获的异常,我怀疑首先启动任务并稍后应用 then()/catch()
会导致一些计时问题。
对于我的问题的任何改进或更好的解决方案,我们表示赞赏。例如。我的解决方案只允许“分批”重试。如果有人提出更好的连续解决方案,我们也将不胜感激。
最佳答案
使用 await
和 asnyc
可以以更清晰的方式解决这个问题。
您将一组tasks
(执行时启动给定任务的函数)传递给execute_tasks
。此函数将为每个任务调用 execute_task
,将任务函数传递给它,execute_task
将返回一个 Promise,其中包含任务成功与否的信息。
execute_task
作为一个循环,一直循环到异步任务成功或达到最大重试次数。
因为每个任务都有自己的重试循环,所以您可以避免这些波浪。每个任务在失败时都会将其自身排队等待新的执行。以这种方式使用 await
创建某种协作式多任务处理。所有错误都会得到处理,因为任务是在 try catch
block 中执行的。
function wait(ms, data) {
return new Promise((resolve, reject) => setTimeout(() => {
if (Math.random() > 0.5) {
resolve(data);
} else {
reject(new Error());
}
}, ms));
}
async function execute_task(task) {
let result, lastError;
let i = 0
//loop until result was found or the retry count is larger then 10
while (!result && i < 10) {
try {
result = await task()
} catch (err) {
lastError = err
// maybe sleep/wait before retry
}
i++
}
if (result) {
return { success: true, data: result }
} else {
return { success: false, err: lastError }
}
}
async function execute_tasks(taskList) {
var taskPromises = taskList.map(task => execute_task(task))
// the result could be sorted into failed and not failed task before returning
return await Promise.all(taskPromises)
}
var taskList = []
for (let i = 0; i < 10; i++) {
taskList.push(() => {
return wait(500, {
foo: i
})
})
}
execute_tasks(taskList)
.then(result => {
console.dir(result)
})
关于javascript - 同步多个 Promise,同时允许多次重试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52095711/