promise的使用

240 阅读3分钟

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阶段,新版的主流浏览器可用。在这里看兼容性

image.png

Promise.race

Promise.race接收一个promise的iterable类型(例如,一个数组其中每个元素都是一个promise)并返回一个promise。 第一个promise的状态改变时(不管结果本身是成功状态还是失败状态),就返回那个结果

Promise.any

接收一个接收一个promise的iterable类型(例如,一个数组其中每个元素都是一个promise)并返回一个promise。 执行逻辑是:

  • 只要其中的一个 promise 成功,就返回那个已经成功的 promise 。
  • 如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise 

它的使用场景: 当一个数据有多个来源时,可以同时发出去,然后以先回来的为主。例如,获取天气预报的信息有三个接口都可以提供,那就可以用Promise.race同时发,谁先回来就用谁的数据。