Promise 中的辅助方法

315 阅读2分钟

在上一篇 Promise的介绍中,已经把PromiseA+的规范实现了一遍,今天把非规范中的辅助方法实现一遍,自己做个记录,方便以后查找

一共要实现这么几个

静态方法
  • resolve
  • race
  • all
  • race
原型方法
  • catch
  • finally

静态方法

resolve

resolve 可以传入普通属性和一个 promise类型,如果传递了promise,则会使用传递 promise 的状态

Promise.resolve(10).then(res=>{
  console.log(res) // 10
})

Promise.resolve(new Promise((resolve,reject)=>{
  resolve(100)
})).then(res=>{
    console.log(res) // 100
})

Promise.resolve 中还可以继续调用 then 链,所以要返回一个新的promise

所以我们可以写出这样的代码

class Promise {
  constructor(executor) {
    const onFulfilled = val => {
      if (this.status == PENGING) {
        if (val instanceof Promise) {
          return val.then(onFulfilled, onRejected);
        }
        // ....
      }
    };
    executor(onFulfilled);
  }

  static resolve(val) {
    return new Promise((resolve, rejcet) => {
      resolve(val);
    });
  }
}

reject

reject 也是同样的步骤,只不过,reject 不需要深度递归,因为外层 reject了,内部的Promise成功失败与否不重要了

 static reject(err) {
    return new Promise((resolve, rejcet) => {
      rejcet(err);
    });
  }

all

all 方法必须所有的状态都是成功,才可以成功,只要有一个失败状态,就会走入失败 先看用法

Promise.all([Promise.resolve(10),2,3]).then(res=>{
  console.log(res) // [10,2,3]
},err=>{
  console.log(err)
})

all 方法可以接受普通值,也可以接收一个 promise 类型,并且返回一个按照传入顺序的结果数组

由于 all 也可以调用 then 链,所以也需要返回一个 新的 promise

  static all(arr) {
   if(arr.length == 0){
      return Promise.resolve([])
   }
    return new Promise((resolve, rejcet) => {
      let len = arr.length,
        ret = [];
      arr.forEach((val, idx) => {
        Promise.resolve(val).then(res => {
          ret[idx] = res;
          if (--len == 0) {
            resolve(ret);
          }
        }, rejcet);
      });
    });
  }

race

比较两个 promise 的速度,哪个先快执行哪个

Promise.race([2,3,1]).then(res=>{
  console.log(res) // 2
})

同样的,依然需要返回一个 新的 promise

static race(arr) {
    return new Promise((resolve, reject) => {
      arr.forEach(val => {
        Promise.resolve(val).then(resolve, reject);
      });
    });
  }

所以,all 传入一个 空数组,可以在 then 中返回一个空数组,race 传入一个空数组,不会有任何反应

举个 race 例子,如果一个请求超过 2s 以后自动取消,可以使用 rece 来比较请求的promise和自定义promise更改状态的时间

let p1 =  new Promise(resolve => {
 // 模拟请求
  setTimeout(() => {
    resolve(10);
  }, 1000);
});

function withRabort(userPromise) {
  let p,abort;
  const innerPromise = new Promise((resolve, reject) => {
   abort = reject;
  });
  p = Promise.race([userPromise, innerPromise]);
  p.abort = abort
  return p;
}

let p = withRabort(p1)

setTimeout(()=>{
  p.abort("失败")
},2000)

原型方法

catch

Promise.reject(100).catch(res=>{
  console.log(res)
})

比较简单

catch(callback) {
    this.then(null, callback);
  }

finally

不论成功或者失败都会执行

let p = new Promise((resolve)=>{
  resolve(10)
})

p.then(res=>res).finally(res=>{
  console.log(res,"finally") // undefined finally
})

finally 中是无法获得传递的 参数的,如果想获取,可以在callback()改为callback(value)

  finally(callback) {
    // value
    return this.then(
      value => this.resolve(callback()).then(() => value),
      reason =>
        this.resolve(callback()).then(() => {
          throw reason;
        })
    );
  }