Promise源码解读(二)-手写promise剩余方法实现

6 篇文章 0 订阅
5 篇文章 0 订阅

Promise源码解读(二)-手写promise剩余方法实现

静态resolve函数实现

   // 添加静态resolve方法
  static resolve (value) {
    // 如果参数是MyPromise实例,直接返回这个实例
    if (value instanceof MyPromise) return value
    return new MyPromise(resolve => resolve(value))
  }

静态resolve函数其实是返回一个新的MyPromise实例,并立即执行resolve函数。

静态reject函数实现

 // 添加静态reject方法
  static reject (value) {
    return new MyPromise((resolve ,reject) => reject(value))
  }

静态reject函数其实是返回一个新的MyPromise实例,并立即执行reject函数。

catch函数实现

// 添加catch方法
  catch (onRejected) {
    return this.then(undefined, onRejected)
  }

实现思路基本思路:

其实catch函数是then(null, rejection) 的别名,用于指定发生错误时的回调函数。
由于promise处理错误的回调函数只能有一个入口,所以对then函数优化如下:

then(onFulfilled,onRejected){
      switch (this.status) {
        case MyPromise.PNEDING:
         //错误处理队列,只添加一个错误处理回调函数
          if(this.rejectCallback.length<1&&MyPromise.isFunction(onRejected)){
            this.rejectCallback.push(onRejected);
          }
          break
        case MyPromise.RESOLVED:
          onFulfilled(this.value)
          break
        case MyPromise.REJECTED:
          onRejected(this.value)
          break
      }
      return this;
    }

效果

new MyPromise(function(reslove,reject){
  reject("错误");
}).then((v)=>{
  console.log(v)
}).catch((v)=>{
  console.log(v+"123") //错误123
}).catch((v)=>{
  console.log(v+"456") //不会出现
});

静态函数all

Promise.all 方法的参数不一定是数组,但是必须具有 iterator 接口,且返回的每个成员都是 Promise 实例

最简版本

 //添加静态all方法
    static all(list){
      return new MyPromise((resolve, reject) => {
       let value=[];
          for(let [i,p] of list.entries()){
           p.then((v)=>{
             value.push(v)
           })
          }
          resolve(value)
      },err=>{
        reject(err);
      })
      }
let p1=MyPromise.resolve("123");
let p2=MyPromise.resolve("456");
let p3=MyPromise.resolve("789");

let p=MyPromise.all([p1,p2,p3]).then((v)=>{
  console.log(v)
});

实现思路基本思路:

创建一个容器用来存放多个MyPromise对象转态结束的值,最后在经过MyPromise的resolve函数一次性返回结果。

优化版本

// 添加静态all方法
  //添加静态all方法
    static all(list){
      return new MyPromise((resolve, reject) => {
       let values=[];
       let count=0;
          for(let [i,p] of list.entries()){
            // 数组参数如果不是MyPromise实例,先调用MyPromise.resolve
            this.resolve(p).then((v)=>{
              values[i] = v;
              count++;
              // 所有状态都变成fulfilled时返回的MyPromise状态就变成fulfilled
              if(count===list.length)resolve(values)
            })
          }
      },err=>{
        // 有一个被rejected时返回的MyPromise状态就变成rejected
        reject(err);
      })
    }
let p1=new MyPromise((resolve,reject)=>{
  setTimeout(()=>{
    resolve("123");
  },1000)
})
let p2=MyPromise.resolve("456");
let p3=MyPromise.resolve("789");
let p4="101112";

let p=MyPromise.all([p1,p2,p3,p4]).then((v)=>{
  console.log(v)
});

静态race函数

Promise.race 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例

// 添加静态race方法
  static race (list) {
    return new MyPromise((resolve, reject) => {
      for (let p of list) {
        // 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变
        this.resolve(p).then(res => {
          resolve(res)
        }, err => {
          reject(err)
        })
      }
    })
  }

实现思路基本思路:

返回一个新的MyPromise,主要传入promise集合有一个状态发生变化,则新的MyPromise状态跟着改变

finally函数

在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。

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

实现思路基本思路:

利用then函数,主动触发静态resolve函数。

静态any函数(实验性)

TC39 第四阶段草案(Stage 4)

接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise 和AggregateError类型的实例,它是 Error 的一个子类,用于把单一的错误集合在一起。本质上,这个方法和Promise.all()是相反的。

// 添加静态any方法
    static any(list) {
      return new MyPromise((resolve, reject) => {
      //如果传入的参数是一个空的可迭代对象,则返回一个 已完成(already resolved) 状态的 	Promise。
        if(list.length===0)resolve();
        let count=0;
        for (let p of list) {
          this.resolve(p).then((v)=>{
          //只要传入的迭代对象中的任何一个 promise 变成成功(resolve)状态
            resolve(v)
          },(v)=>{
            count++
            let e=new Error("全部错误");
            //所有的 promises 都失败,那么返回的 promise 就会 异步地(当调用栈为空时) 变成成功/失败(resolved/reject)状态。
            if(count===list.length)reject(e);
          })
        }
      },err=>{
        reject(err);
      })
    }

实现思路基本思路:

参考all函数实现思路

最后

至此文章已经把promise方法除静态方法allSettled函数这个方法留给读者们自由实现。

以下是完整的代码

class MyPromise{
   static PNEDING='pending';
   static RESOLVED='funfilled';
   static REJECTED='rejected';

   constructor(executor){
     this.status=MyPromise.PNEDING;
     this.value=null;
     this.resolveCallback=[];
     this.rejectCallback=[];
     try {
       executor(this._resolve.bind(this),this._reject.bind(this));
     } catch (error) {
       this._reject(error)
     }
   }
   static isFunction(val){
     return typeof val=="function";
   }
   _resolve(value){
     if(value instanceof MyPromise){
       return value.then(this.resolve.bind(this),this.reject.bind(this))
     }
     setTimeout(() => {
       if(this.status===MyPromise.PNEDING){
         this.status=MyPromise.RESOLVED;
         this.value=value;
         this.resolveCallback.forEach(cb=>this.value=cb(this.value))
       }
     }, 0);
   }
   _reject(value){
     setTimeout(() => {
     if(this.status===MyPromise.PNEDING){
          this.status=MyPromise.REJECTED
          this.value=value
            this.rejectCallback.forEach(cb=>cb(value))
        }
       }, 0);
     }
   // 添加静态resolve方法
   static resolve (value) {
     // 如果参数是MyPromise实例,直接返回这个实例
     if (value instanceof MyPromise) return value
     return new MyPromise(resolve => resolve(value))
   }
   // 添加静态reject方法
   static reject (value) {
     return new MyPromise((resolve ,reject) => reject(value))
   }
   //添加静态all方法
   static all(list){
     return new MyPromise((resolve, reject) => {
      let values=[];
      let count=0;
         for(let [i,p] of list.entries()){
           // 数组参数如果不是MyPromise实例,先调用MyPromise.resolve
           this.resolve(p).then((v)=>{
             values[i] = v;
             count++;
             // 所有状态都变成fulfilled时返回的MyPromise状态就变成fulfilled
             if(count===list.length)resolve(values)
           })
         }
     },err=>{
       // 有一个被rejected时返回的MyPromise状态就变成rejected
       reject(err);
     })
   }
   // 添加静态race方法
 static race (list) {
   return new MyPromise((resolve, reject) => {
     for (let p of list) {
       // 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变
       this.resolve(p).then(res => {
         resolve(res)
       }, err => {
         reject(err)
       })
     }
   })
 }
   // 添加静态any方法
   static any(list) {
     return new MyPromise((resolve, reject) => {
       if(list.length===0)resolve();
       let count=0;
       for (let p of list) {
         this.resolve(p).then((v)=>{
           resolve(v)
         },(v)=>{
           count++
           let e=new Error("全部错误");
           if(count===list.length)reject(e);
         })
       }
     },err=>{
       reject(err);
     })
   }
   then(onFulfilled,onRejected){
     switch (this.status) {
       case MyPromise.PNEDING:
         this.resolveCallback.push(onFulfilled);
         if(this.rejectCallback.length<1&&MyPromise.isFunction(onRejected)){
           this.rejectCallback.push(onRejected);
         }
         break
       case MyPromise.RESOLVED:
         onFulfilled(this.value)
         break
       case MyPromise.REJECTED:
         onRejected(this.value)
         break
     }
     return this;
   }
   // 添加catch方法
 catch (onRejected) {
   return this.then(undefined, onRejected)
 }
 finally (cb) {
   return this.then(
     value  => MyPromise.resolve(cb()).then(() => value),
     reason => MyPromise.resolve(cb()).then(() => { throw reason })
   );
 }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值