Promise
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
基本语法
它的基本语法是 new Promise 同时传入一个固定格式的函数,它会得到一个Promise对象。这个固定格式的函数有两个参数,如果要将Promise对象的状态设置为resolved就调用第一个参数,如果要将它的状态设置为rejected就调用第二个参数。同时状态的改变就会执行对应的实例方法:从pending(等待) -> resolved(成功)就会执行.then方法。从pending -> rejected 就会执行.catch方法,最后一定会执行finally。
一般可以使用Promise来改写一些需要回调的处理的异步操作,例如原生ajax, node中的文件异步读写,以获取更好的编程体验。
还可以利用Promise.then是微任务的特点模拟一些异步操作(vue的nextTick就用到了)。
静态方法
除了常用的promise.then, catch, finall, Promise.resovle, Promise.reject等。它还有一些比较重要的api,如下:
Promise.all
Promise.all接收一个promise的iterable类型(例如,一个数组其中每个元素都是一个promise)并返回一个promise对象,为表述方便,记为p。
- 当所有Promise对象的状态是resolved时,p.then返回一个结果数组;
- 任意一个Promise失败时,p.catch则返回最先被reject的失败状态。
伪代码如下:
Promise.all([Promise1,...PromiseN]).then(res => {
// console.log(res.map(it => it.data))
console.log('全部成功了',res.length)
console.log(res)
}).catch(err => {
console.log('谁先失败了')
console.log(err)
})
它的使用场景是页面上有多个并列的请求(请求之间没有逻辑先后关系)要发出去,就使用它。例如用户进入电商页面时,请求商品列表信息和请求排行版信息就可以同时发。
Promise.allSettled
Promise.allSettled的入参和返回值与Promise.all格式一致,但它的执行逻辑是:当每一个 promise 已经完成(无论是成功的达成或被拒绝),所返回的 promise.then包含原始 promises 集中每个 promise 的结果。 伪代码如下:
Promise.allSettled([Promise1,...PromiseN]).then(res => {
console.log('全部完成了',res.length)
console.log(res)
// [{status:'fulfilled', value:promise的值}, ... {status:'rejected', reason:失败的原因} ]
})
对于每个结果对象,都有一个 status 字符串。
- 如果它的值为
fulfilled,则结果对象上存在一个value。{status:'fulfilled', value:promise的值} - 如果值为
rejected,则存在一个reason。{status:'rejected', reason:失败的原因}
它目前处在stage 4阶段,新版的主流浏览器可用。在这里看兼容性
Promise.race
Promise.race接收一个promise的iterable类型(例如,一个数组其中每个元素都是一个promise)并返回一个promise。 第一个promise的状态改变时(不管结果本身是成功状态还是失败状态),就返回那个结果
Promise.any
接收一个接收一个promise的iterable类型(例如,一个数组其中每个元素都是一个promise)并返回一个promise。 执行逻辑是:
- 只要其中的一个
promise成功,就返回那个已经成功的promise。 - 如果可迭代对象中没有一个
promise成功(即所有的promises都失败/拒绝),就返回一个失败的promise
它的使用场景: 当一个数据有多个来源时,可以同时发出去,然后以先回来的为主。例如,获取天气预报的信息有三个接口都可以提供,那就可以用Promise.race同时发,谁先回来就用谁的数据。