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 都会作为微任务在本轮调用结束之后就执行了