2

一、引言

这周末,突然想起小组读书打卡还有一个撸一个Promise的任务还没有完成,虽然我之前有试过撸一个Promise,但是没试过使用PromiseA+来测试,所以打算写一篇wiki来记录一下我实现的这一个过程。

二、自己写一个Promise需要做什么

首先,我们要明确我们要实现一个Promise需要去做什么。

1.因为新建Promise要用到new关键字,所以我们需要将手动实现的Promise封装成一个类;

2.因为new Promise()的参数是一个函数,所以手动实现的Promise的参数是一个函数

3.因为传进Promise里面的函数还有两个参数resolve函数和reject函数,这两个函数的作用是改变Promise的状态;

4.promise对象有三个状态pending, fullfilled, rejected,初始状态为pending,调用resolve会将其改为fullfilled,调用reject会改为rejected,而且Promise对象的状态一旦发生改变便不能再变为其他的状态,有且只有pending变为fullfilled和pending变为rejected两种可能

5.promise实例对象建好后可以调用then方法,而且是可以链式调用then方法,说明then是一个实例方法。也就是说调用了then方法之后返回的也是一个promise实例对象

三、分步实现

明确了我们需要做什么,那接下来二话不说开撸。但是我们不可能一口气吃成一个胖子,所以我们需要按照上面写到的步骤一步步实现。

第一步:实现基本的框架

//先定义三个状态
const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';

class MyPromise {
    constructor(fn) {
          this.status = PENDING;      //初状态为pending
        this.value = null;          //初始化value
        this.reason = null;         //初始化reason
      
        //定义resolve方法
        this.resolve = (value) => {
            if(this.status === PENDING) {
                this.status = FULLFILLED;
                this.value = value;
            }
        }

        //定义rejecte方法
        this.reject = (reason) => {
            if(this.status === PENDING) {
                this.status = REJECTED;
                this.reason = reason;
            }
        }

        //将resolve和reject作为参数调用传进来的参数,加上try...catch,一旦发生错误就调用reject
        try {
            fn(this.resolve, this.reject);
        } catch(error) {
            this.reject(error);
        }

        this.then = this.then.bind(this);
    }

    then(onFullfilled, onRejected) {
        //fullfilled状态则会调用onFullfilled函数
        if(this.status === FULLFILLED) {
            onFullfilled(this.value);
        }

        //rejected状态则会调用onRejected函数
        if(this.status === REJECTED) {
            onRejected(this.reason);
        }
    }
}

这样,我们基本的框架就已经成形了,但是,then函数那里很明显是有缺陷的,试想,如果传递给then函数的参数onFullfilled和onRejected如果不是一个函数呢,那这样肯定会报错的,所以我们then函数里面添加这样的一个判断:如果传递进来的参数不是一个函数,则直接返回value和reason的error。

then(onFullfilled, onRejected) {
    //如果onFulfilled不是函数,给一个默认函数,返回value
    let realOnFullfilled = onFullfilled;
    if(typeof realOnFullfilled !== 'function') {
      realOnFullfilled = (value) => value;
    }

    //如果onRejected不是函数,给一个默认函数,返回reason的error
    let realOnRejected = onRejected;
    if(typeof realOnRejected !== 'function') {
      realOnRejected = (reason) => {
        throw reason;
      }
    }

    //fullfilled状态则会调用onFullfilled函数
    if(this.status === FULLFILLED) {
      onFullfilled(this.value);
    }

    //rejected状态则会调用onRejected函数
    if(this.status === REJECTED) {
      onRejected(this.reason);
    }
}

第二步:明确then方法是什么时候执行

如果只是像上面这样写的话,如果我执行下面的代码:

new Promise(fn).then(onFulfilled, onRejected);

这时候,不管fn的异步操作有没有结束,then方法都会马上执行,这显然是不合理的。我们需要的是当fn里面的异步操作成功或失败(即是status从pending变为fullfilled或者rejected)之后才会去执行then方法。如果要实现这个先后顺序该怎么办呢?

很简单,只要我们限制onFulfilled和onRejected执行的时机就可以了,那该怎么限制呢?

很明显,我们是需要等到status从pending变为fullfilled或者rejected才会去执行onFulfilled或onRejected。那如果fn的异步操作还没有完成(即是status还未从pending变为fullfilled或者rejected)怎么办?

很简单,那就把onFulfilled和onRejected先用一个数组暂存起来呗等到fn的异步操作完成即是status从pending变为fullfilled或者rejected),标志就是fn中的resolve或reject函数执行,再去执行onFulfilled或者onRejected就行了。

好了,分析这么多,干吧!

这个是then方法里面补充的:

then(onFullfilled, onRejected) {
  //省略其他的代码
  //如果还是PENDING状态,将回调保存下来
  if(this.status === PENDING) {
    this.onFullfilledCallbacks.push(realOnFullfilled);
    this.onRejectedCallbacks.push(realOnRejected);
  }
}

这个是在resolve方法和reject方法里面补充的:

//定义resolve方法
this.resolve = (value) => {
  if(this.status === PENDING) {
    this.status = FULLFILLED;
    this.value = value;
    //fn状态由pending变成fullfilled,执行then里面的onFullfilled回调函数
    this.onFullfilledCallbacks.forEach(callback => {
      callback(this.value);
    })
  }
}

//定义rejecte方法
this.reject = (reason) => {
  if(this.status === PENDING) {
    this.status = REJECTED;
    this.reason = reason;
    //fn状态由pending变成rejected,执行then里面的onRejected回调函数
    this.onRejectedCallbacks.forEach(callback => {
      callback(this.reason);
    })
  }
}

好了,我们已经完成上面的设想了,现在可以来测试一波:

因为使用到了request模块,自然是要装上的:

npm install --save-dev request

因为在这里我使用了ES6,但是node还没有完全支持ES6,所以这里配置了一下package.json:

{
  "name": "test",
  "version": "",
  "type": "module",            //要将type设置为module,node就可以支持ES6而不需要装babel
  "devDependencies": {
    "babel-register": "^6.26.0",
    "promises-aplus-tests": "^2.1.2",
    "request": "^2.88.2"
  },
  "scripts": {
    "test": "promises-aplus-tests MyPromise"
  },
  "dependencies": {
    "koa": "^2.13.0"        //这个可以忽略掉
  }
}

最后,在终端运行:

node MyPromiseTest.js

MyPromiseTest.js

import MyPromise from './MyPromise.js';
import request from 'request';
import babel from 'babel-register';

let promise1 = new MyPromise((resolve) => {
    request('https://www.baidu.com', (error, response) => {
        if(!error && response.statusCode === 200) {
            resolve('request1 success');
        }
    });
});

promise1.then((value) => console.log(value));

let promise2 = new MyPromise((resolve, reject) => {
    request('https://www.baidu.com', (error, response) => {
        if(!error && response.statusCode === 200) {
            reject('request2 failed');
        }
    });
});

promise2.then((value) => {
    console.log(value);
}, (reason) => {
    console.log(reason);
});

测试结果:
image.png
第一第二步测试通过,no problem!

第三步:实现then方法的返回值,使then方法能够链式调用

到这里为止,其实我们已经可以实现异步调用了,只是then的返回值还没实现,还不能实现链式调用。根据规范then的返回值必须是一个promise。根据要求的不同情况,选择分步处理。

1.如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e。

解决办法:每次执行onFulfilled 或者 onRejected新建一个promise,使用try...catch语句快捕获到执行执行onFulfilled 或者 onRejected过程中抛出的错误,并且使用reject方法处理它。

//如果还是PENDING状态,也不能直接保存回调方法了,需要包一层来捕获错误
if(this.status === PENDING) {
  // this.onFullfilledCallbacks.push(realOnFullfilled);
  // this.onRejectedCallbacks.push(realOnRejected);
  let promise2 = new MyPromise((resolve, reject) => {
    this.onFullfilledCallbacks.push(() => {
      try {
        realOnFullfilled(this.value);
      } catch(error) {
        reject(error);
      }
    });
    this.onRejectedCallbacks.push(() => {
      try {
        realOnRejected(this.reason);
      } catch(error) {
        reject(error);
      }
    });
  });

  return promise2;
}

//fullfilled状态则会调用onFullfilled函数
if(this.status === FULLFILLED) {
  let promise2 = new MyPromise((resolve, reject) => {
    //这里不能简单的调用realOnFullfilled函数了,要使用try...catch语句块抱起来,如果有错就reject
    try {
      realOnFullfilled(this.value);
    } catch(error) {
      reject(error);
    }
  });

  return promise2;
}

//rejected状态则会调用onRejected函数
if(this.status === REJECTED) {
  let promise2 = new MyPromise((resolve, reject) => {
    //这里不能简单的调用realOnRejected函数了,要使用try...catch语句块抱起来,如果有错就reject
    try {
      realOnRejected(this.reason);
    } catch(error) {
      reject(error);
    }
  });

  return promise2;
}

2.如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值

解决办法:判断状态为FULLFILLED的时候,添加一层判断,判断onFullfilled是不是函数。如果不是,直接resolve,如果是,先执行onFullfilled函数,再resolve。

//这只是一个例子,每个onFullfilled函数都要这样写
//fullfilled状态则会调用onFullfilled函数
if(this.status === FULLFILLED) {
  let promise2 = new MyPromise((resolve, reject) => {
    //这里不能简单的调用realOnFullfilled函数了,要使用try...catch语句块抱起来,如果有错就reject
    try {
      //加一层onFullfilled是不是函数的判断
      if(typeof onFullfilled !== 'function') {
        resolve(this.value);        //返回相同的值
      } else {
        realOnFullfilled(this.value);
        resolve(this.value);
      }
    } catch(error) {
      reject(error);
    }
  });

  return promise2;
}

3.如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的拒因。

解决办法:判断状态为REJECTED的时候,添加一层判断,判断onRejected是不是函数。如果不是,直接reject,如果是,先执行onRejected函数,再resolve。

//这只是一个例子,每个onRejected函数都要这样写
//rejected状态则会调用onRejected函数
if(this.status === REJECTED) {
  let promise2 = new MyPromise((resolve, reject) => {
    //这里不能简单的调用realOnRejected函数了,要使用try...catch语句块抱起来,如果有错就reject
    try {
      //加一层onRejected是不是函数的判断
      if(typeof onRejected !== 'function') {
        reject(this.reason);
      } else {
        realOnRejected(this.reason);
        resolve();
      }
    } catch(error) {
      reject(error);
    }
  });

  return promise2;
}

4.如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x)

解决办法:因为多了这一条规则,所以我们还需要对成功调用onFullfilled函数或onRejected函数的返回值做判断,如果有返回值就要进行Promise解决过程。所以我们需要封装一个方法来进行Promise解决过程,暂且将这个方法命名为resolvePromise吧。

//这只是一个例子,其余相似的地方也要这样写
//fullfilled状态则会调用onFullfilled函数
if(this.status === FULLFILLED) {
  let promise2 = new MyPromise((resolve, reject) => {
    //这里不能简单的调用realOnFullfilled函数了,要使用try...catch语句块抱起来,如果有错就reject
    try {
      //加一层onFullfilled是不是函数的判断
      if(typeof onFullfilled !== 'function') {
        resolve(this.value);        //返回相同的值
      } else {
        let x = realOnFullfilled(this.value);           //x是执行OnFullfilled函数的返回值
        resolvePromise(promise2, x, resolve, reject);   // 调用Promise 解决过程
      }
    } catch(error) {
      reject(error);
    }
  });

  return promise2;
}

第四步:Promise解决过程

规则太多了,都放进代码里面了,这个很简单,就是按照规则实现就好了

function resolvePromise(promise, x, resolve, reject) {
    //如果promise和x指向同一对象,以TypeError为拒因拒绝执行promise
    if(promise === x) {
        return reject(new TypeError('The promise and the return value are the same'));
    }

    if(x instanceof MyPromise) {
        //如果x为promise,则使promise接受x的状态
        //也就是继续执行x,如果执行的时候拿到了一个y,还要继续解析y
        x.then((y) => {
            resolvePromise(promise, y, resolve, reject);
        }, reject);
    } else if(typeof x === 'object' || typeof x === 'function') {
        //如果x为对象或函数
        if(x === null) {
            return resolve(x);
        }
        try {
            //把x.then赋给then
            var then = x.then;
        } catch(error) {
            return reject(error);
        }

        //如果then是函数
        if(typeof then === 'function') {
            let called = false;         //called表示resolvePromise或者rejectPromise被调用
            //将x作为函数的作用域this调用
            //传递两个回调函数作为参数,第一个参数叫做resolvePromise,第二个参数叫做rejectPromise
            try {
                then.call(
                    x,
                    //如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
                    //resolvePromise
                    (y) => {
                        //如果resolvePromise和rejectPromise均被调用
                        //或者同一参数被调用了多次,则优先采用首次调用并忽略剩下的调用
                        if(called) return;
                        called = true;
                        resolvePromise(promise, y, resolve, reject);
                    },
                    (r) => {
                        if(called) return;
                        called = true;
                        reject(r);
                    }
                );
            } catch(error) {
                //如果调用then方法抛出了异常e,
                //如果resolvePromise或者rejectPromise已经被调用,则忽略之
                if(called) return;
                reject(error);
            }
        } else {
            //如果then不是函数,以x为参数执行promise
            resolve(x);
        }
    } else {
        //如果x不为对象或函数,以x为参数执行promise
        resolve(x);
    }
}

第五步:onFulfilled 和 onRejected 的执行时机

在规范中还有一条:onFulfilled 和 onRejected 只有在执行环境堆栈仅包含平台代码时才可被调用。这一条的意思是实践中要确保 onFulfilled 和 onRejected 方法异步执行且应该在 then 方法被调用的那一轮事件循环之后的新执行栈中执行。所以在我们执行onFulfilled 和 onRejected的时候都应该包到setTimeout里面去

添加了setTimeout的then方法:

then(onFullfilled, onRejected) {
  //如果onFulfilled不是函数,给一个默认函数,返回value
  let realOnFullfilled = onFullfilled;
  if(typeof realOnFullfilled !== 'function') {
    realOnFullfilled = (value) => value;
  }

  //如果onRejected不是函数,给一个默认函数,返回reason的error
  let realOnRejected = onRejected;
  if(typeof realOnRejected !== 'function') {
    realOnRejected = (reason) => {
      throw reason;
    }
  }

  //如果还是PENDING状态,也不能直接保存回调方法了,需要包一层来捕获错误
  if(this.status === PENDING) {
    // this.onFullfilledCallbacks.push(realOnFullfilled);
    // this.onRejectedCallbacks.push(realOnRejected);
    let promise2 = new MyPromise((resolve, reject) => {
      this.onFullfilledCallbacks.push(() => {
        //这里加setTimeout
        setTimeout(() => {
          try {
            if(typeof onFullfilled !== 'function') {
              resolve(this.value);
            } else {
              let x = realOnFullfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);   // 调用Promise 解决过程
            }
          } catch(error) {
            reject(error);
          }
        }, 0);
      });
      this.onRejectedCallbacks.push(() => {
        //这里加setTimeout
        setTimeout(() => {
          try {
            if(typeof onRejected !== 'function') {
              reject(this.reason);
            } else {
              let x = realOnRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);   // 调用Promise 解决过程
            }
          } catch(error) {
            reject(error);
          }
        }, 0);
      });
    });

    return promise2;
  }

  //fullfilled状态则会调用onFullfilled函数
  if(this.status === FULLFILLED) {
    let promise2 = new MyPromise((resolve, reject) => {
      //这里要添加setTimeout,保证回调在下一轮事件循环开始的时候执行
      setTimeout(() => {
        //这里不能简单的调用realOnFullfilled函数了,要使用try...catch语句块抱起来,如果有错就reject
        try {
          //加一层onFullfilled是不是函数的判断
          if(typeof onFullfilled !== 'function') {
            resolve(this.value);        //返回相同的值
          } else {
            let x = realOnFullfilled(this.value);           //x是执行OnFullfilled函数的返回值
            resolvePromise(promise2, x, resolve, reject);   // 调用Promise 解决过程
          }
        } catch(error) {
          reject(error);
        }
      }, 0);
    });

    return promise2;
  }

  //rejected状态则会调用onRejected函数
  if(this.status === REJECTED) {
    let promise2 = new MyPromise((resolve, reject) => {
      //这里要添加setTimeout,保证回调在下一轮事件循环开始的时候执行
      setTimeout(() => {
        //这里不能简单的调用realOnRejected函数了,要使用try...catch语句块抱起来,如果有错就reject
        try {
          //加一层onRejected是不是函数的判断
          if(typeof onRejected !== 'function') {
            reject(this.reason);
          } else {
            let x = realOnRejected(this.reason);           //x是执行OnRejected函数的返回值
            resolvePromise(promise2, x, resolve, reject);   // 调用Promise 解决过程
          }
        } catch(error) {
          reject(error);
        }
      }, 0);
    });

    return promise2;
  }
}

第六步:实现一个静态方法deferred

官方对这个方法的定义如下:

  • deferred: 返回一个包含{ promise, resolve, reject }的对象
  • promise 是一个处于pending状态的promise
  • resolve(value) 用value解决上面那个promise
  • reject(reason) 用reason拒绝上面那个promise

代码如下:

MyPromise.deferred = () => {
    let result = {};
    result.promise = new MyPromise((resolve, reject) => {
        result.resolve = resolve;
        result.reject = reject;
    });

    return result;
}

四、测试

1.先下载测试的工具:

npm install --save-dev promises-aplus-tests

2.重新配置package.json:

{
  "name": "test",
  "version": "",
  //"type": "module",            //将这个删掉,因为测试使用的是CommonJS语法
  "devDependencies": {
    "babel-register": "^6.26.0",
    "promises-aplus-tests": "^2.1.2",
    "request": "^2.88.2"
  },
  "scripts": {
    "test": "promises-aplus-tests MyPromise"
  },
  "dependencies": {
    "koa": "^2.13.0"        //这个可以忽略掉
  }
}

3.在MyPromise.js的文末将MyPromise抛出:

//省略上面的代码
module.exports = MyPromise;

4.运行npm脚本:

npm run test

5.测试结果:
image.png
872用例全通过!!!

五、实现Promise其他的方法

1.Promise.resolve()

将现有对象转为Promise对象,如果 Promise.resolve 方法的参数,不是具有 then 方法的对象(又称 thenable 对象),则返回一个新的 Promise 对象,且它的状态为fulfilled。

实现代码如下:

resolve(parameter) {
  if(parameter instanceof MyPromise) {
    //如果是传入的参数是Promise对象,则返回对象本身
    return parameter;
  }

  //如果传入的参数不是一个thenable对象,则返回一个新的promise对象,且状态变为fullfilled
  return new MyPromise((resolve) => {
    resolve(parameter);
  })
}

2.Promise.reject()

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected

实现代码如下:

reject(reason) {
  //返回一个新的promise实例,该实例的状态为rejected
  return new MyPromise((resolve, reject) => {
    reject(reason);
  })
}

3.Promise.all()

该方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.all([p1, p2, p3]);

Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会先调用Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。当p1, p2, p3全部resolve,大的promise才resolve,有任何一个reject,大的promise都reject

实现代码如下:

all(promiseList) {
  return new MyPromise((resolve, reject) => {
    var count = 0;      //用来统计promiseList中promise实例resolve的个数
    var length = promiseList.length;
    var result = [];    //用来存放promiseList中resolved的promise的返回值

    if(length === 0) {
      //如果传递进来的是空数组,直接resolve
      resolve(result);
    }

    promiseList.forEach((promise, index) => {
      //将数组中的每一个元素都使用Promise.resolve()方法变为promise对象
      MyPromise.resolve(promise).then((value) => {
        count++;
        result[index] = value;
        if(count === length) {
          //只有当所有的promise实例都resolve,新对象的状态才会变成resolved,
          //并且将每个promise成功后的返回值组成数组传递给新的promise对象的回调函数
          return resolve(result);
        }
      }, (reason) => {
        //只要有一个promise实例被reject,返回的promise对象的状态就变为rejected,
        //且第一个被reject的实例对象的返回值会被传递给新的promise对象的回调函数
        return reject(reason);
      });
    });
  });
}

4.Promise.race()

该方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.race([p1, p2, p3]);

该方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变那个率先改变的 Promise 实例的返回值,就传递给p的回调函数

实现代码:

race(promiseList) {
  return new MyPromise((resolve, reject) => {
    let length = promiseList.length;

    if(length === 0){
      return resolve();
    }

    promiseList.forEach((promise) => {
      MyPromise.resolve(promise).then((value) => {
        //只要有一个promise被resolve,返回的新的promise实例就被resolve
        return resolve(value);
      }, (reason) => {
        //只要有一个promise被reject,返回的新的promise实例就被reject
        return reject(reason);
      });
    });
  });
}

5.Promise.prototype.catch()

Promise.prototype.catch方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。

实现代码如下:

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

6.Promise.prototype.finally()

finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。

实现代码如下:

finally(callback) {
  //无论如何都会执行callback,并且返回原来的值
  return this.then(
    value => MyPromise.resolve(callback()).then(() => value),
    reason => MyPromise.resolve(callback()).then(() => {throw reason})
  )
}

7.Promise.allSettled

该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束。该方法由 ES2020 引入。该方法返回的新的 Promise 实例,一旦结束,状态总是fulfilled,不会变成rejected。状态变成fulfilled后,Promise 的监听函数接收到的参数是一个数组,每个成员对应一个传入Promise.allSettled()的 Promise 实例的执行结果

实现代码:

allSettled(promiseList) {
  //只有当所有的promise实例都返回结果(不管是resolve还是reject)才会结束
  //只会被resolve,不会被reject
  return new MyPromise((resolve, reject) => {
    var length = promiseList.length;
    var result = [];
    var count = 0;

    if(length === 0) {
      return resolve(result);
    }

    promiseList.forEach((promise, index) => {
      MyPromise.resolve(promise).then((value) => {
        count++;
        result[index] = {
          status: 'fullfilled',
          value: value
        };
        if(count === length) {
          return resolve(result);
        }
      }, (reason) => {
        count++;
        result[index] = {
          status: 'rejected',
          reason: reason
        };
        if(count === length) {
          return resolve(result);
        }
      });
    });
  });
}

8.Promise.any()

用法:

const p = Promise.any([p1, p2, p3]);

Promise.any()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。

实现代码:

any(promiseList) {
  //只有所有的promise都被reject时,新的promise对象才会被reject
  //一旦由promise被resolve时,新的promise对象就被resolve
  return new MyPromise((resolve, reject) => {
    var length = promiseList.length;
    var count = 0;
    var result = [];

    if(length === 0) {
      return resolve(result);
    }

    promiseList.forEach((promise, index) => {
      MyPromise.resolve(promise).then((value) => {
        return resolve(value);
      }, (reason) => {
        count++;
        result[index] = reason;
        if(count === length) {
          return reject(result);
        }
      });
    });
  });
}

六、总结

写这篇东西写了一整天了,也终于实现了一个比较完整的Promise,写完之后发现自己对Promise的了解变得更加透测,觉得很多东西还是需要看懂源码并且自己使用原生js实现一遍才能真正透测的理解它。由于源码过长,所以我将它推上了GitHub,附上源码的地址:https://github.com/lugezuishuai/Promise-realization


JacksonHuang
74 声望3 粉丝