promise.all() & Promise.race()

Promise.all()

有时候页面需要多个接口请求的局面,我们需要一个判断所有的请求都结束了的时机

var promise = Promise.all([
  ajax('/api/users.json'),
  ajax('/api/posts.json')
])

promise.then(function (values) {
  console.log(values)
}).catch(function (error) {
  console.log(error)
})

这个方法需要接受的是一个数组,数组中的每一个元素都是一个Promise对象,我们可以把每一个Promise对象都视为一个异步任务,所有的Promise都完成之后才会.then,这里面的values就是所有异步任务的结果组成的数组,有一个失败了就会被catch捕获到错误

组成使用串行和并行:

ajax('/api/urls.json')
  .then(value => {
    const urls = Object.values(value)
    const tasks = urls.map(url => ajax(url))
    return Promise.all(tasks)
  })
  .then(values => {
    console.log(values)
  })

Promise.race()

和all不同,跟着所有任务中的第一个完成的任务一起结束。
比如这里有一个实现5s超时管理的例子:

// Promise.race 实现超时控制

const request = ajax("/api/posts.json");
const timeout = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error("timeout")), 500);
});

Promise.race([request, timeout])
  .then((value) => {
    console.log(value);
  })
  .catch((error) => {
    console.log(error);
  });

执行时序

先来看一张图:

为什么会先调用Promise而不是setTimeout0秒立即执行呢?
要明白这一点我们要先搞清楚一些概念

宏任务 & 微任务

  • 有一种说法:回调队列中的任务被称之为宏任务
    宏任务执行过程中,会临时追加一些额外的需求,在这个时候可以选择成为一个新的宏任务,重新排队,比如setTimeout就会作为宏任务排队
  • 也可以作为微任务,在当前任务结束之后立刻执行
    Promise的回调就是作为微任务执行的。

微任务就是为了提高页面的响应能力而引用的。目前大部分的异步调用都是作为宏任务进入回调队列。
Promise、MutationObserver,nodejs中的process.nextTick 都会作为微任务在本轮调用结束之后就执行了

最后修改:2024 年 03 月 21 日
收款不要了,给孩子补充点点赞数吧