手写promise

47 阅读8分钟

1.写promise构造器

  • 就是写new Promise()的过程

(1)constructor传递两个参数reject和reslove,new Promise时立即调用

(2)resolvereject可以被调用,所以他们两个是函数

(3)resolvereject被调用时改变当前promise的状态(得到两个属性):promise的状态结果(状态有pending[初始状态],fulfilled,rejected)

console.log(Promise.resolve(1)) image.png (4)因此在调用reslove和reject时就是改变状态和结果,要注意的是promise的状态只能改变一次就不能更改了,使用在写reslove和reject函数时要先检查状态是否改变

class MyPromise{
    //设置私有属性,这两个为状态和结果的初始值
    #state = 'pending'
    #result = undefined
    constructor(executor){
        //设置resolve和reject
        const resolve = (value)=> {
            if(this.#state !== 'pending') return
            //改变状态和结果
            this.#state = 'fulfilled'
            this.#result = value
        }
        const reject = (reason)=> {
            if(this.#state !== 'pending') return
            this.#state = 'rejected'
            this.#result = reason
        }
        executor()
    }
}

这里优化一下写法:相近的语句写成函数+软编码

const PENDING = 'pending';
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
    //设置私有属性,这两个为状态和结果的初始值
    #state = 'pending'
    #result = undefined
    #changeState = function(state,result){
        //校验
        if(this.#state !== PENDING) return
        //改变状态和结果
        this.#state = state
        this.#result = result
    }
    constructor(executor){
        //设置resolve和reject
        const resolve = (value)=> {
           this.#changeState(FULFILLED,value)
        }
        const reject = (reason)=> {
           this.#changeState(REJECTED,reason)
        }
        
        executor(resolve,reject)
    }
}

(5)在执行promise的时候抛出错误,状态变为rejected,结果为抛出的结果,所以executor用try catch包住,这里要注意的是在promise中只能捕获同步错误,**异步错误无法捕获

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
  //设置私有属性,这两个为状态和结果的初始值
  #state = "pending";
  #result = undefined;
  #changeState = function (state, result) {
    //校验
    if (this.#state !== PENDING) return;
    //改变状态和结果
    this.#state = state;
    this.#result = result;
  };
  constructor(executor) {
    //设置resolve和reject
    const resolve = (value) => {
      this.#changeState(FULFILLED, value);
    };
    const reject = (reason) => {
      this.#changeState(REJECTED, reason);
    };
    try {
      executor(resolve, reject);
    } catch (error) {
      //掉reject把状态变为rejected
      reject(error);
    }
  }
}

2.then

我们知道promise的then方法接收两个回调返回一个promise

这时候有两个问题

image.png

  • 一.then什么时候执行成功的方法onFulfilled,什么时候执行失败的方法onRejected
  • 二.then调用返回的promise什么时候为成功resolve,什么时候失败reject

一 解决onFulfilled和onRejected调用问题

1.当前的promise为完成状态时调用onFulfilled,状态为拒绝就调用onRejected

2.promise为pending状态也要解决(比如放在setTimeout中),而then方法中不知道是不是等待状态,可以看到#changeState中可以判断状态,但是#changeState中拿不到onFulfilled等这四个东西

then方法操作步骤

  • 把这4个包成对象放进数组(用数组装是因为可能多次调用then有多个)
  • thenchangeState中调用一个方法run
  • 如果promise处于等待pending的状态,等状态改变了,(等待->fullfilled/rejected)就调用run开始执行

run方法:

  • 如果是pending就return
  • 如果状态是fulfilledrejected就执行onFulfilledonRejected,执行前记得判断传入的是不是函数

image.png

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
  //设置私有属性,这两个为状态和结果的初始值
  #state = "pending";
  #result = undefined;
  #handlers = []; //装fulFilled,rejected,resolve,reject的数组

  //改变状态
  #changeState = function (state, result) {
    //校验
    if (this.#state !== PENDING) return;
    //改变状态和结果
    this.#state = state;
    this.#result = result;
    //调用run
    this.#run();
  };

  //执行那四个
  #run = function () {
    if (this.#state == PENDING) return;
    //如果数组不为空就执行
    while (this.#handlers.length) {
      //一个个拿出来执行,用shift删除并返回的一个元素
      const { onFulfilled, onRejected, resolve, reject } =
        this.#handlers.shift();
      if (this.#state === FULFILLED) {
        if (typeof onFulfilled === "function") {
          onFulfilled(this.#result);
        }
      } else {
        if (typeof onRejected === "function") {
          onRejected(this.#result);
        }
      }
    }
  };

  constructor(executor) {
    //设置resolve和reject
    const resolve = (value) => {
      this.#changeState(FULFILLED, value);
    };
    const reject = (reason) => {
      this.#changeState(REJECTED, reason);
    };
    try {
      executor(resolve, reject);
    } catch (error) {
      //掉reject把状态变为rejected
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      //1.放进数组
      this.#handlers.push({
        onFulfilled,
        onRejected,
        resolve,
        reject,
      });
      //2.调用run
      this.#run();
    });
  }
}

到此onFulfilledonRejected什么时候执行已经完成

二 解决返回的promise什么时候完成,什么时候失败

- 当对应的回调传入的不是函数时,进行穿透,promise原来为什么状态现在就为什么状态

  if (this.#state === FULFILLED) {
        if (typeof onFulfilled === "function") {
          onFulfilled(this.#result);
        } else {
          resolve(this.#result);
        }
      } else {
        if (typeof onRejected === "function") {
          onRejected(this.#result);
        } else {
          reject(this.#state);
        }
      }

- 返回的是函数

if (typeof onFulfilled === "function") {
          try {
            const data = this.onFulfilled(this.#result)
            resolve(data)
          } catch (error) {
            reject(error)
          }
        } else {
          resolve(this.#result);
        }

优化一下代码

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
  //设置私有属性,这两个为状态和结果的初始值
  #state = "pending";
  #result = undefined;
  #handlers = []; //装fulFilled,rejected,resolve,reject的数组

  //改变状态
  #changeState = function (state, result) {
    //校验
    if (this.#state !== PENDING) return;
    //改变状态和结果
    this.#state = state;
    this.#result = result;
    //调用run
    this.#run();
  };

  //提出公共代码
  #runOne = function (callback, resolve, reject) {
    if (typeof callback !== "function") {
      const settled = this.#state === FULFILLED ? resolve : reject;
      settled(this.#result);
      return;
    }
    try {
      //成功
      const data = callback(this.#result);
      resolve(data);
    } catch (error) {
      //失败
      reject(error);
    }
  };
  //执行那四个
  #run = function () {
    if (this.#state == PENDING) return;
    //如果数组不为空就执行
    while (this.#handlers.length) {
      //一个个拿出来执行,用shift删除并返回的一个元素
      const { onFulfilled, onRejected, resolve, reject } =
        this.#handlers.shift();

      if (this.#state === FULFILLED) {
        this.#runOne(onFulfilled, resolve, reject);
      } else {
        this.#runOne(onRejected, resolve, reject);
      }
    }
  };

  //构造器
  constructor(executor) {
    //设置resolve和reject
    const resolve = (value) => {
      this.#changeState(FULFILLED, value);
    };
    const reject = (reason) => {
      this.#changeState(REJECTED, reason);
    };
    try {
      executor(resolve, reject);
    } catch (error) {
      //掉reject把状态变为rejected
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      //1.放进数组
      this.#handlers.push({
        onFulfilled,
        onRejected,
        resolve,
        reject,
      });
      //2.调用run
      this.#run();
    });
  }
}

- 调用函数的返回结果是一个promise

这里要先写一个判断是不是promise的函数(一个东西只要有属性then并且then是一个函数,那么就是promise)

 #isPromise = function(value){
    if(value !== null && (typeof value === 'object' || typeof value === 'function')){
        return typeof value.then === 'function'
    }
    return false
  }
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
  //设置私有属性,这两个为状态和结果的初始值
  #state = "pending";
  #result = undefined;
  #handlers = []; //装fulFilled,rejected,resolve,reject的数组

  //改变状态
  #changeState = function (state, result) {
    //校验
    if (this.#state !== PENDING) return;
    //改变状态和结果
    this.#state = state;
    this.#result = result;
    //调用run
    this.#run();
  };

  //判断是不是promise
  #isPromise = function(value){
    if(value !== null && (typeof value === 'object' || typeof value === 'function')){
        return typeof value.then === 'function'
    }
    return false
  }

  //放进微队列
  #runMicroTask = function(fun){
    //node环境
    if(typeof process === 'object' && typeof process.nextTick === 'function'){
        process.nextTick(fun)
    }else if(typeof MutationObserver === 'function'){
        const ob = new MutationObserver(fun)
        const textNode = document.createTextNode('1')
        ob.observe(textNode,{
            characterData:true
        })
        textNode.data = '2'
    }else{
        setTimeout(fun,0)
    }
  }

  //提出公共代码
  #runOne = function (callback, resolve, reject) {
    if (typeof callback !== "function") {
      const settled = this.#state === FULFILLED ? resolve : reject;
      settled(this.#result);
      return;
    }
    try {
      //成功
      const data = callback(this.#result);
      //判断传入函数的返回结果是不是promise
        if(this.#isPromise(data)){
            //是promise就调then,promise是完成就调resolve,失败就调reject
            data.then(resolve,reject)
        }else{
            resolve(data)
        }
      resolve(data);
    } catch (error) {
      //失败
      reject(error);
    }
  };
  //执行那四个
  #run = function () {
    if (this.#state == PENDING) return;
    //如果数组不为空就执行
    while (this.#handlers.length) {
      //一个个拿出来执行,用shift删除并返回的一个元素
      const { onFulfilled, onRejected, resolve, reject } =
        this.#handlers.shift();

      if (this.#state === FULFILLED) {
        this.#runOne(onFulfilled, resolve, reject);
      } else {
        this.#runOne(onRejected, resolve, reject);
      }
    }
  };

  //构造器
  constructor(executor) {
    //设置resolve和reject
    const resolve = (value) => {
      this.#changeState(FULFILLED, value);
    };
    const reject = (reason) => {
      this.#changeState(REJECTED, reason);
    };
    try {
      executor(resolve, reject);
    } catch (error) {
      //掉reject把状态变为rejected
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      //1.放进数组
      this.#handlers.push({
        onFulfilled,
        onRejected,
        resolve,
        reject,
      });
      //2.调用run
      this.#run();
    });
  }
}

三 其他操作

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
  //设置私有属性,这两个为状态和结果的初始值
  #state = "pending";
  #result = undefined;
  #handlers = []; //装fulFilled,rejected,resolve,reject的数组

  //改变状态
  #changeState = function (state, result) {
    //校验
    if (this.#state !== PENDING) return;
    //改变状态和结果
    this.#state = state;
    this.#result = result;
    //调用run
    this.#run();
  };

  //判断是不是promise
  #isPromise = function(value){
    if(value !== null && (typeof value === 'object' || typeof value === 'function')){
        return typeof value.then === 'function'
    }
    return false
  }

  //放进微队列
  #runMicroTask = function(fun){
    //node环境
    if(typeof process === 'object' && typeof process.nextTick === 'function'){
        process.nextTick(fun)
    }else if(typeof MutationObserver === 'function'){
        const ob = new MutationObserver(fun)
        const textNode = document.createTextNode('1')
        ob.observe(textNode,{
            characterData:true
        })
        textNode.data = '2'
    }else{
        setTimeout(fun,0)
    }
  }

  //提出公共代码
  #runOne = function (callback, resolve, reject) {
    if (typeof callback !== "function") {
      const settled = this.#state === FULFILLED ? resolve : reject;
      settled(this.#result);
      return;
    }
    try {
      //成功
      const data = callback(this.#result);
      //判断传入函数的返回结果是不是promise
        if(this.#isPromise(data)){
            //是promise就调then,promise是完成就调resolve,失败就调reject
            data.then(resolve,reject)
        }else{
            resolve(data)
        }
      resolve(data);
    } catch (error) {
      //失败
      reject(error);
    }
  };
  //执行那四个
  #run = function () {
    if (this.#state == PENDING) return;
    //如果数组不为空就执行
    while (this.#handlers.length) {
      //一个个拿出来执行,用shift删除并返回的一个元素
      const { onFulfilled, onRejected, resolve, reject } =
        this.#handlers.shift();

      if (this.#state === FULFILLED) {
        this.#runOne(onFulfilled, resolve, reject);
      } else {
        this.#runOne(onRejected, resolve, reject);
      }
    }
  };

  //构造器
  constructor(executor) {
    //设置resolve和reject
    const resolve = (value) => {
      this.#changeState(FULFILLED, value);
    };
    const reject = (reason) => {
      this.#changeState(REJECTED, reason);
    };
    try {
      executor(resolve, reject);
    } catch (error) {
      //掉reject把状态变为rejected
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      //1.放进数组
      this.#handlers.push({
        onFulfilled,
        onRejected,
        resolve,
        reject,
      });
      //2.调用run
      this.#run();
    });
  }
  //处理错误的回调
  catch(onRejected){
    //直接调then,给成功部分传undefined
    return this.then(undefined,onRejected)
  }

  //不论成功失败都要执行
  //也返回一个promise,跟当前promise状态一至
  finally(onFinally){
    return this.then((data)=>{
        onFinally()
        return 
    },(err)=>{
        onFinally()
        throw err
    })
  }

  //如果参数是promise就直接返回promise,
  //如果是一个A+规范的,即有一个then方法的对象或函数就调用then方法
  static resolve(value){
    if(value instanceof MyPromise) return value
    //因为静态方法中不能调用实例方法,所以把resolve和reject提出来
    let _resolve,_reject
    const p = new MyPromise((resolve,reject)=>{
        _resolve = resolve
        _reject = reject
    })
    if(p.#isPromise(value)){
        value.then(_resolve,_reject)
    }else{
        _resolve(value)
    }
    return p
  }

  //不管传什么都返回一个promise,promise里直接拒绝
  static reject(value){
    return new MyPromise((resolve,reject)=>{
        reject(value)
    })
  }

  //promise的all方法
  static all(value){
    let res,rej
    //返回的是一个promise
    const p = new MyPromise((resolve,reject)=>{
      res = resolve
      rej = reject
    })
    //设置p的状态
    //1.如果传的是个空数组返回成功的空数组
    //2.不为空就遍历全部
    let count = 0//记录数组中有几个元素
    const result = []//存储结果
    let finish = 0//完成的数量
    for(let item of value){
      let i = count
      count++

      MyPromise.resolve(item)//保证每项都是promise
      .then(data=>{
        //成功的数据放到result中
        result[i] = data
        //判断是否全部遍历
        finish++
        if(finish === count){
          res(result)
        }

      },rej)//一个失败会导致全部失败,所以失败直接传rej

    }
    if(count === 0){
      return this.resolve(result)
    }
    return p
  }
}