如何将包含异步任务的for循环封装为Promise并等待所有任务完成
解决方案
你的问题核心是循环内的fetchData是异步操作,throttle包装后的执行也是非阻塞的,代码不会等待这些异步任务完成就直接执行了最后的callback。我们只需要把每个异步任务封装为Promise,收集所有Promise后用Promise.all等待全部执行完毕再触发回调即可。
修改后的完整代码如下:
const loop = (callback) => { // 收集所有异步任务的Promise const promises = []; for(const domain of domains) { // 每个domain的任务封装为Promise推入数组 promises.push(new Promise((resolve) => { throttle(() => { fetchData(domain) .then((data) => { if (data[0]) { // 修正原代码中typeof的错误用法 if ( typeof data[1] === undefined || typeof data[1]?.settings?.[1]?.protocol === undefined ) { // 此处可补充你的空分支逻辑 } else { data = data[1]; if ( data.settings[1].protocol != "IMAP" || providerExist(data.domain) ) { return; } addProvider( data.domain, data.settings[1].address, data.settings[1].port ); } } }) .catch((err) => { console.log(`${err}`); }) .finally(() => { // 无论当前任务成功失败都标记完成,避免单个请求错误卡住整体流程 resolve(); }); }); })); } // 等待所有异步任务执行完成后再调用回调 Promise.all(promises).then(() => callback()); }
注意事项
- 原代码中
typeof的使用存在语法错误,把整个判断表达式放进了typeof的参数中,导致判断逻辑完全不生效,上述代码已修正该问题,同时新增可选链避免深层属性读取时报错。 - 如果你需要只有所有请求全部成功时才执行回调、出错就中断流程,可以去掉
finally里的resolve,把resolve放到then逻辑的末尾,catch中调用reject即可。 - 如果你使用的
throttle函数本身支持返回Promise,可以直接返回节流函数的执行结果,不需要额外封装一层Promise。
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

