likes
comments
collection
share

聊聊Promise

作者站长头像
站长
· 阅读数 54

前言

面试官:

你在工作中有使用到promise吗?

all,race方法有什么区别知道吗?

怎么捕捉promise错误?

我们来做一道经典的面试题?

聊聊Promise

这题我记着背过啊,先同步在异步,然后微任务,宏任务。。。。,然后就没有然后了

什么是promise

Promises/A+规范:promisesaplus.com/#notes

具体使用

// 基础使用
// 1.Promise 是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
// 2.Promise 中有三种状态 分别为 成功 fulfilled 失败 rejected 等待pending
// pending->fulfilled
// pending->rejected
// 一旦状态确定就不可更改

// 3. resolve和reject函数是用来更改状态的
//  resolve:fulfilled
//  reject:rejected
// 4. then方法内部做的事情就判断状态 如果状态是成功  调用成功的回调函数 如果是状态失败 调用失败的回调函数 then方法是定义在原型上的
// 5.then 成功回调有一个参数 表示成功之后的值 then失败回调有一个参数 表示失败后的原因
const MyPromise = require("./myPromise");

new Promise((resolve, reject) => {
    resolve('成功') //返回成功值
    // reject('失败')  //返回错误结果
});

实现Promsie

定义基础类

// 定义基础状态
const PENDING = "pending"; //等待
const FULFILLED = "fulfiled"; //成功
const REJECTED = "rejected"; //失败

// 实现基础类

class Mypromise {
  constructor(executor) {
    // 捕获执行器错误
    try {
      executor(resolve, reject);
    } catch (error) {
        this.reject(error)
    }
  }
  //promise状态
  status = PENDING;
  //   成功之后的值
  vlaue = undefined;
  // 失败后的原因
  reason = undefined;
  resolve = (value) => {
    // 如果状态不是等待  阻止程序向下执行
    if (this.status != PENDING) return;
    //将状态更改为成功
    this.status = FULFILLED;
    // 保存成功之后的值
    this.value = value;
  };
  reject = (reason) => {
    // 如果状态不是等待  阻止程序向下执行
    if (this.status != PENDING) return;
    //将状态更改为失败
    this.status = REJECTED;
    //保存失败后的原因
    this.reason = reason;
  };
  then(successCallback, failCallback) {
    //判断状态
    if (this.status === FULFILLED) {
      // 调用成功回调
      successCallback(this.value);
    } else {
      //调用失败回调
      failCallback(this.reason);
    }
  }
}
module.exports = Mypromise;

处理异步逻辑

如果是pending状态下对回调进行缓存

  then(successCallback, failCallback) {
    //判断状态
    if (this.status === FULFILLED) {
      // 调用成功回调
      successCallback(this.value);
    } else if (this.status === REJECTED) {
      //调用失败回调
      failCallback(this.reason);
    } else {
      this.successCallback = successCallback;
      this.failCallback = failCallback;
    }
  }
  resolve = (value) => {
    // 如果状态不是等待  阻止程序向下执行
    if (this.status != PENDING) return;
    //将状态更改为成功
    this.status = FULFILLED;
    // 保存成功之后的值
    this.value = value;
    //判断成功回调是否存在,如果存在调用
    this.successCallback && this.successCallback(this.value);
  };
  reject = (reason) => {
    // 如果状态不是等待  阻止程序向下执行
    if (this.status != PENDING) return;
    //将状态更改为失败
    this.status = REJECTED;
    //保存失败后的原因
    this.reason = reason;
    //判断失败回调是否存在,如果存在 调用
    this.failCallback && this.failCallback(this.reason);
  };

实现then方法多次调用

将回调修改为数组进行存储

  then(successCallback, failCallback) {
    //判断状态
    if (this.status === FULFILLED) {
      // 调用成功回调
      successCallback(this.value);
    } else if (this.status === REJECTED) {
      //调用失败回调
      failCallback(this.reason);
    } else {
        // pending状态下处理逻辑
        // 将成功回调和失败回调存储起来
      this.successCallback.push(successCallback);
      this.failCallback.push(failCallback);
    }
  }

遍历数组,执行回调

  resolve = (value) => {
    // 如果状态不是等待  阻止程序向下执行
    if (this.status != PENDING) return;
    //将状态更改为成功
    this.status = FULFILLED;
    // 保存成功之后的值
    this.value = value;
    //判断成功回调是否存在,如果存在调用
    // this.successCallback && this.successCallback(this.value);

    while(this.successCallback.length){
        this.successCallback.shift()(this.value)
    }

  };
  reject = (reason) => {
    // 如果状态不是等待  阻止程序向下执行
    if (this.status != PENDING) return;
    //将状态更改为失败
    this.status = REJECTED;
    //保存失败后的原因
    this.reason = reason;
    //判断失败回调是否存在,如果存在 调用
    // this.failCallback && this.failCallback(this.reason);
    while(this.failCallback.length){
        this.failCallback.shift()(this.reason)
    }
  };

实现then方法链式调用

  then(successCallback, failCallback) {
    let promise2 = new Mypromise((resolve, reject) => {
      //判断状态
      if (this.status === FULFILLED) {
        // 调用成功回调
        let x = successCallback(this.value);
        //    判断x的值是普通值还是promise对象
        //    如果是普通值  直接调用resolve
        //    如果是promise对象 查看promise对象返回的结果
        //    再根据promise对象返回的结果  决定调用resolve 还是调用reject

        resolvePromise(x, resolve, reject);
      } else if (this.status === REJECTED) {
        //调用失败回调
        failCallback(this.reason);
      } else {
        // pending状态下处理逻辑
        // 将成功回调和失败回调存储起来
        this.successCallback.push(successCallback);
        this.failCallback.push(failCallback);
      }
    });

    return promise2;
  }
  
  function resolvePromise(x, resolve, reject) {
  if (x instanceof Mypromise) {
    x.then(resolve, reject);
  } else {
    //普通值
    resolve(x);
  }
}

实现then方法链式调用识别promise对象自调用

  then(successCallback, failCallback) {
    let promise2 = new Mypromise((resolve, reject) => {
      //判断状态
      if (this.status === FULFILLED) {
        // 变为异步代码
        setTimeout(() => {
          let x = successCallback(this.value);
          //    判断x的值是普通值还是promise对象
          //    如果是普通值  直接调用resolve
          //    如果是promise对象 查看promise对象返回的结果
          //    再根据promise对象返回的结果  决定调用resolve 还是调用reject

          resolvePromise(promsie2, x, resolve, reject);
        }, 0);
      } else if (this.status === REJECTED) {
        //调用失败回调
        failCallback(this.reason);
      } else {
        // pending状态下处理逻辑
        // 将成功回调和失败回调存储起来
        this.successCallback.push(successCallback);
        this.failCallback.push(failCallback);
      }
    });

    return promise2;
  }
  
function resolvePromise(promise2, x, resolve, reject) {
  //判断是不是返回了自己
  if (promise2 === x) {
    return reject(new TypeError(""));
  }
  if (x instanceof Mypromise) {
    x.then(resolve, reject);
  } else {
    //普通值
    resolve(x);
  }
}

错误捕获

执行器错误捕获

class Mypromise{
  constructor(executor) {
    //   捕获执行器错误
    try {
      executor(resolve, reject);
    } catch (error) {
      this.reject(error);
    }
  }
}

对回调执行进行错误捕获并返回

  then(successCallback, failCallback) {
    let promise2 = new Mypromise((resolve, reject) => {
      //判断状态
      if (this.status === FULFILLED) {
        // 变为异步代码
        setTimeout(() => {
          try {
            let x = successCallback(this.value);
            //    判断x的值是普通值还是promise对象
            //    如果是普通值  直接调用resolve
            //    如果是promise对象 查看promise对象返回的结果
            //    再根据promise对象返回的结果  决定调用resolve 还是调用reject

            resolvePromise(promsie2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0);
      } else if (this.status === REJECTED) {
        // 变为异步代码
        setTimeout(() => {
          try {
            let x = failCallback(this.reason);
            //    判断x的值是普通值还是promise对象
            //    如果是普通值  直接调用resolve
            //    如果是promise对象 查看promise对象返回的结果
            //    再根据promise对象返回的结果  决定调用resolve 还是调用reject

            resolvePromise(promsie2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0);
      } else {
        // pending状态下处理逻辑
        // 将成功回调和失败回调存储起来
        this.successCallback.push(() => {
          setTimeout(() => {
            try {
              let x = successCallback(this.value);
              //    判断x的值是普通值还是promise对象
              //    如果是普通值  直接调用resolve
              //    如果是promise对象 查看promise对象返回的结果
              //    再根据promise对象返回的结果  决定调用resolve 还是调用reject

              resolvePromise(promsie2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        });
        this.failCallback.push(() => {
          setTimeout(() => {
            try {
              let x = failCallback(this.reason);
              //    判断x的值是普通值还是promise对象
              //    如果是普通值  直接调用resolve
              //    如果是promise对象 查看promise对象返回的结果
              //    再根据promise对象返回的结果  决定调用resolve 还是调用reject

              resolvePromise(promsie2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        });
      }
    });

    return promise2;
  }

将then方法的参数修改为可选参数

then(successCallback, failCallback){
  // 给回调新增默认值
    successCallback = successCallback ? successCallback :value => value;
    failCallback = failCallback ? failCallback : reason => {throw reason};
}

实现promise.all()方法

  static all(array){
    //结果数组
    let result=[]
    let index=0

    return new Mypromise((resolve,reject)=>{
        function addData(key,value){
            result[key] =value
            index++
            if(index===array.length){
                resolve(result)
            }
        }
        for(let i=0;i<array.length;i++){
            let current = array[i]
            if(current instanceof Mypromise){
                //promise对象
                current.then(value=>addData(i,value),reason=>reject(reason))
            }else{
                //普通值
                addData(i,array[i])
            }
        }
    })
  }

promise.resolve()方法实现

  static resolve(value) {
    if (value instanceof Mypromise) return vlaue;
    // 如果传递不是promise类型转为promise再返回
    return new Mypromise((resolve) => resolve(value));
  }

Promise.prototype.finally()方法实现

  finally(callback) {
    // 实现异步返回
    return this.then(
      (value) => {
        return Mypromise.resolve(callback()).then(() => value);
      },
      (reason) => {
        callback();
        return Mypromise.resolve(callback().then(()=>{throw reason}))
      }
    );
  }

Promise.prototype.catch()方法实现

  catch(failCallback){
   return this.then(undefined,failCallback)
  }

promise.race()方法实现

  static race(array){
    return new MyPromise((resolve,reject)=>{
        for (let i = 0; i < array.length; i++) {
            let current = array[i];
            current.then(
                (value) => resolve(value),
                (reason) =>{
                  reject(reason) 
                }
              );
        }
    })
  }

promise.allSettled()方法实现

  static allSettled(array){
    const result=[]
    let index = 0;
    return new MyPromise((resolve,reject)=>{
      function addData(key, value,status) {
        result[key] = {status:status,value};
        index++;
        if (index === array.length) {
          resolve(result);
        }
      }
      for (let i = 0; i < array.length; i++) {
        let current = array[i];
        if (current instanceof MyPromise) {
          // promise对象
          current.then(
            (value) => addData(i, value,'fulfilled'),
            (reason) =>addData(i,reason,'rejected')
          );
        } else {
          //普通值
          addData(i, array[i]);
        }
      } 


    })
  }

promise.any()方法实现

  static any(array){
    let errs=[]
    let len =array.length
    return new MyPromise((resolve,reject)=>{
      for (let i = 0; i < array.length; i++) {
        let current = array[i];
        if (current instanceof MyPromise) {
          current.then(value=>resolve(value),err=>{
              len--
              errs.push(err)
              if(len===0){
                reject(new AggregateError(errs))
              }
          })
        }
  
      }
    })

  }

最后

如果你能看到这里,并且把所有代码亲自实现过一遍,开头的问题对你来说也就不是问题了,对于那道经典的面试题可能还需要掌握一些知识,也就是js的事件循环,这也是下篇文章要讲的内容了,且听下回分解,如果觉得这篇文章对你有帮助的话,帮忙点一下赞,salut!

转载自:https://juejin.cn/post/7245613765692768313
评论
请登录