[JavaScript]_ 认识Promise (五)

107 阅读2分钟

这是我参与2022首次更文挑战的第28天,活动详情查看:2022首次更文挑战」。

期约连锁与期约合成

期约连锁就是一个期约接一个期约地拼接,期约合成是将多个期约组合为一个期约。

期约连锁

在前面有讲过,Promise的实例方法,如then()、catch()、finally()这些实例方法都会返回一个新的Promise对象,而这个新的Promise对象又有自己的实例方法,就这样可以实现把Promise逐个串联起来。

Promise解决 回调地狱 的问题就用了这一特性

// 回调地狱,回调函数深入嵌套
function fn(str, cb=null) {
    setTimeout(()=> {
        console.log(str);
        cb && cb()
    },1000)
}
fn('p1', () => {
   fn('p2', () => {
       fn('p3', () => {
    
       }) 
   }) 
})
// p1 (1s后)
// p2 (2s后)
// p3 (3s后)

// Promise
let p1 = new Promise((resolve, reject) => {
    console.log('p1');
    setTimeout(resolve, 1000);
})
p1.then(() => new Promise((resolve, reject) => {
    console.log('p2')
    setTimeout(resolve, 1000)
})).then(() => new Promise((resolve, reject) => {
    console.log('p3')
    setTimeout(resolve, 1000)
}))
// p1 
// p2 (1s后)
// p3 (2s后)

期约合成

Promise 类提供两个将多个期约实例组合成一个期约的静态方法:Promise.all()和 Promise.race()。

Promise.all()

这个静态方法创建的期约会在一组期约全部解决之后再解决。它接收一组可迭代的对象。

let p = Promise.all([
    Promise.resolve(1),
    Promise.resolve(2)
])
// p    Promise {<fulfilled>: Array(2)}
p.then((e) => {
    console.log(e) //  [1, 2]
})

传入不同的参数情况:

  1. 如果不传参数呢?或不可迭代?
let p = Promise.all();

报错了 image.png

  1. 如果迭代对象中的元素不是Promise对象呢?
let p1 = Promise.all([1,2,3])
let p2 = Promise.all([]);

image.png

可迭代对象的元素被Promise.resolve()转换成了期约

  1. 如果包含待定的或拒绝的呢?
let p1 = Promise.all([Promise.resolve(1), Promise.reject(2)]); // Promise {<rejected>: 2}
let p2 = Promise.all([new Promise(()=> {}), Promise.resolve(2)]); // Promise {<pending>}
let p3 = Promise.all([Promise.resolve(1), Promise.reject(2),Promise.reject(3)]); // Promise {<rejected>: 2}

  • 有拒绝的就合成拒绝的Promise, 有pending的就合成pending状态的Promise;
  • 以第一个拒绝的Promise理由就是合成的Promise对象的拒绝理由
  • 会静默处理所有包含期约的拒绝操作

Promise.race()

这个方法同样是接收一个可迭代对象,返回一个新的Promise对象。它返回的这个Promise对象是一组集合中最先解决或拒绝的Promise的镜像。

let p = Promise.race([
    Promise.resolve(1),
    Promise.resolve(2)
])
// Promise {<fulfilled>: 1}

传入不同的参数情况同 Promise.all()一样,不多做解释。

这里就强调一点:Promise.race() 返回的新期约 是包装的第一个落定的期约结果,不管是解决还是拒绝平等对待。