【发布时间】:2019-02-05 07:42:14
【问题描述】:
我正在尝试构建一个自动重试下载的下载器。基本上,一个任务队列,它重试任务一定次数。我第一次尝试使用Promise.all(),但绕过第一次拒绝失败described here 的“技巧”没有帮助(并且是该线程中进一步描述的反模式)
所以我得到了一个版本,它似乎在某种程度上符合我的要求。至少它打印的结果是正确的。但它仍然会抛出几个uncaught exception test 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 次)所有结果。但还是uncaught exceptions飞来飞去。
由于并非所有被拒绝的承诺都会导致未捕获的异常,因此我怀疑,首先启动任务并稍后应用 then()/catch() 会导致一些时间问题。
感谢对我的问题的任何改进或更好的解决方案。例如。我的解决方案只允许“分波”重试。如果有人提出更好的连续解决方案,那也将不胜感激。
【问题讨论】:
-
正如您正确假设的那样,您有时间问题。在您退出内部循环并执行
tasks = failedTasks之前,您推送到failedTasks的重新启动任务可能会再次失败,实际上您没有附加到该 Promise 的.catch回调,直到您在内部循环中再次到达它,所以很有可能您会收到未处理的拒绝错误。 -
"并且是该线程中进一步描述的反模式" - 不,根本不是。在那个答案上查看我的 cmets。
-
@Lniese 我似乎通过稍后添加
.catch()来捕获异常。这是有道理的,但也令人困惑。但我想解释器不知道我是否在稍后发现错误并且必须在某个时候抛出。我想知道是否可以选择说“我稍后会捕捉到这个异常,别担心”@Bergi 感谢您的澄清。我实际上遇到了您警告的问题。好吧,感谢接受的答案,我现在有一个更理智的代码结构。
标签: javascript async-await es6-promise