关于Promise数组的执行疑问?

目前官方:
allSettled: 所有都结束了再将所有结果流转到处理阶段.疑问: 有一个请求很慢是否整体都很慢

第三方:
interval-promise 一个一个执行. 疑问: 有一个请求很慢是否整体都很慢

需求:
根据权限加载页面中不同区域的数据.最终是一个promise数组. 但有的promise会慢一些,希望哪个promise完成了都填充相应的区域

疑问:
promise只能是整体: reject/resolve 才进入处理阶段。作不到哪个完成了执行哪个回调吗

阅读 2.4k
5 个回答

allSettled 和 all 都是一样,要等里面所有 Promise 执行完了才回调。区别在于 allSettled 一定要等完,哪怕是失败。但 all 只要有一个失败就不会等。

下面的代码会输出(不要在意小数):

all: 2.008s
allSettled: 5.013s
function fail(seconds) {
    return new Promise((_, reject) => {
        setTimeout(() => reject(seconds), seconds * 1000);
    });
}

function success(seconds) {
    return new Promise((resolve) => {
        setTimeout(() => resolve(seconds), seconds * 1000);
    });
}

console.time("all");
await Promise.all([fail(2), success(5)]).catch(() => { });
console.timeEnd("all");

console.time("allSettled");
await Promise.allSettled([fail(2), success(5)]).catch(() => { });
console.timeEnd("allSettled");

如果你想每个完成立即就处理,那就不要用 all 或者 allSettled,直接对每个 promise 进行处理就好了,可以用一个循环

promises.forEach(async p => console.log(await p));

注意,如果用 for(i), for...in 或者 for...of,就不要加 await,确实需要等值处理,可以用 async IIFE 再封一层

for (const p of promises) {
    (async () => console.log(await p))();
}

就用 map 之后再用一个 allSettled 来等待完成

const promises = [success(1), fail(2), success(3), success(4)];

console.time("allSettled");
await Promise.allSettled(
    promises.map(async p => console.log(Date.now(), await p.catch(n => `error ${n}`)))
);
console.timeEnd("allSettled");

输出

1679558119617 1
1679558119617 error 2
1679558119617 3
1679558119617 4
allSettled: 4.013s

我觉得根据你的需求,最好是不同的页面区域作为一个单独的组件,这个组件自己负责自己的数据请求和渲染,在请求的过程中显示 loading。

这种模式符合关注点分离的原则,也可以算作是目前的最佳实践。

1、第一个问题,allSettled的确是一个很慢整体很慢

const p1 = new Promise(resolve => setTimeout(() => resolve(1), 5000))
const p2 = 2;
Promise.allSettled([p1, p2]).then(res => console.log(res))

这个会5s后输出
2、这个没用过,看api应该也是的
3、没看懂,你说的是Promise.all吗,做不到。如果你需要那个执行完执行那就不需要promise.all了

第一二个问题确实会整体慢
第三个问题可以使用Promise.race
其他不能中断 那就同步调用

async getList1() {
       
},
async getList2() {
       
},
init(){
  this.getList1();
  this.getList2()
}

allSettled 和 all 一样都用等数组中的所有 promise 实例状态发生变化,使用它们的场景应该是当这些请求全部完成是要做的公共的时,其他独立的内容可以放到 promise 实例中去做,这样就不会因为单个的耗时影响到其他的了。

本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题