手写Promise和Promise中的静态方法

参考博客:
1.zhangpaopao0609
2.齐小神
视频推荐

为什么要有Promise?

为了解决回调地狱问题,也就是函数嵌套函数的问题。例子:
在这里插入图片描述

Promise的实现

Promise 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
Promise是基于Promises/A+规范实现的,可以通过此规范的步骤自己手动实现一个Promise

功能简述

  1. Promise是一个构造函数,new Promise 时传入一个执行函数,并且执行函数是立即执行的
  2. 执行函数接收两个参数 resolve 函数 和 reject 函数,并且均能够接收参数
  3. Promise 的实例上有一个 then 方法, then 方法接收两个参数
  4. 进一步的,promise 有三个状态待定(pending),兑现(fulfilled),拒绝(rejected)。只能从pending到rejected, 或者从pending到fulfilled,状态一旦确认,就不会再改变。通过当前状态判断是否执行成功
  5. 然后就是解决传入promise是异步的问题
  6. 解决.then的链式调用,值的穿透

具体实现代码

const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';

const resolvePromise = (promise2, x, resolve, reject) => {
  // 自己等待自己完成是错误的实现,用一个类型错误,结束掉 promise  Promise/A+ 2.3.1
  if (promise2 === x) { 
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  // Promise/A+ 2.3.3.3.3 只能调用一次
  let called;
  // 后续的条件要严格判断 保证代码能和别的库一起使用
  if ((typeof x === 'object' && x != null) || typeof x === 'function') { 
    try {
      // 为了判断 resolve 过的就不用再 reject 了(比如 reject 和 resolve 同时调用的时候)  Promise/A+ 2.3.3.1
      let then = x.then;
      if (typeof then === 'function') { 
        // 不要写成 x.then,直接 then.call 就可以了 因为 x.then 会再次取值,Object.defineProperty  Promise/A+ 2.3.3.3
        then.call(x, y => { // 根据 promise 的状态决定是成功还是失败
          if (called) return;
          called = true;
          // 递归解析的过程(因为可能 promise 中还有 promise) Promise/A+ 2.3.3.3.1
          resolvePromise(promise2, y, resolve, reject); 
        }, r => {
          // 只要失败就失败 Promise/A+ 2.3.3.3.2
          if (called) return;
          called = true;
          reject(r);
        });
      } else {
        // 如果 x.then 是个普通值就直接返回 resolve 作为结果  Promise/A+ 2.3.3.4
        resolve(x);
      }
    } catch (e) {
      // Promise/A+ 2.3.3.2
      if (called) return;
      called = true;
      reject(e)
    }
  } else {
    // 如果 x 是个普通值就直接返回 resolve 作为结果  Promise/A+ 2.3.4  
    resolve(x)
  }
}

class Promise {
  constructor(executor) {
    this.status = PENDING;
    this.value = undefined;
    this.reason = undefined;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks= [];

    let resolve = (value) => {
      if(this.status ===  PENDING) {
        this.status = FULFILLED;
        this.value = value;
        this.onResolvedCallbacks.forEach(fn=>fn());
      }
    } 

    let reject = (reason) => {
      if(this.status ===  PENDING) {
        this.status = REJECTED;
        this.reason = reason;
        this.onRejectedCallbacks.forEach(fn=>fn());
      }
    }

    try {
      executor(resolve,reject)
    } catch (error) {
      reject(error)
    }
  }

  then(onFulfilled, onRejected) {
    //解决 onFufilled,onRejected 没有传值的问题
    //Promise/A+ 2.2.1 / Promise/A+ 2.2.5 / Promise/A+ 2.2.7.3 / Promise/A+ 2.2.7.4
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
    //因为错误的值要让后面访问到,所以这里也要跑出个错误,不然会在之后 then 的 resolve 中捕获
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
    // 每次调用 then 都返回一个新的 promise  Promise/A+ 2.2.7
    let promise2 = new Promise((resolve, reject) => {
      if (this.status === FULFILLED) {
        //Promise/A+ 2.2.2
        //Promise/A+ 2.2.4 --- setTimeout
        setTimeout(() => {
          try {
            //Promise/A+ 2.2.7.1
            let x = onFulfilled(this.value);
            // x可能是一个proimise
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            //Promise/A+ 2.2.7.2
            reject(e)
          }
        }, 0);
      }

      if (this.status === REJECTED) {
        //Promise/A+ 2.2.3
        setTimeout(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e)
          }
        }, 0);
      }

      if (this.status === PENDING) {
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e)
            }
          }, 0);
        });

        this.onRejectedCallbacks.push(()=> {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0);
        });
      }
    });

    return promise2;
  }
}

常用的Promise静态方法

Promise.all()全部子实例都成功才算成功,有一个子实例失败就算失败

function _all (promises) {
  /*
  * count 计数器,与len比较,判断是否所有的promise都已经成功了
  * result 用于存放成功的结果
  */
  let count=0,len=promises.length, result=[];
  return new Promise((resolve, reject) => {
    // 依次判断传入的promise实例是否成功
    for(let p of promises) {
      Promise.resolve(p).then(res => {
        result[count] = res;
        count++;
        if(count === len) {
          //相等,说明所有的promise实例都成功了, 才可以resolve结果
          resolve(result);
        }
      }).catch(err => 
      //只要有一个失败了就reject出去
      reject(err));
    }
  })
}

Promise.any()有一个子实例成功就算成功,全部子实例失败才算失败

function _any (promises) {
  let result =[],len=promises.length, count=0;
  return new Promise((resolve, reject) => {
    for(let p of promises) {
      Promise.resolve(p).then(res => {
        resolve(res);
      }).catch(err => {
        result[count]=err;
        count++;
        if(count===len){
          reject(result)
        }
      })
    }
  })
} 

Promise.race()用来处理多个请求,采用最快的(谁先完成用谁的)

function _race (promises) {
  return new Promise((resolve, reject) => {
    for(p of promises) {
      Promise.resolve(p).then(res => {
        resolve(res)
      }).catch(err=> reject(err))
    }
  })
} 

Promise.allSettled()返回每个Promised的结果数组,即fulfilled或rejecte

function _allSettled (promises) {
  let result=[],len=promises.length; count=0;
  return new Promise((resolve, reject) => {
    for(let p of promises) {
      Promise.resolve(p).then(res => {
        result[count] ={
          status:'fulfilled',
          result:res
        }
        count++;
        if(count === len) {
          resolve(result)
        }
      }).catch(err => {
        result[count] ={
          status:'rejected',
          result:err
        }
        count++;
        if(count === len) {
          reject(result);
        }
      })
    }
  })
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值