实现一个简单的Promise



  • (1)Promise 基本使用

    var p = new Promise(function(resolve, reject) {
      setTimeout(function() {
        resolve("success");
      }, 1000);
    });
    p.then(success=>{
        console.log(success)
    });
    

    (2)Promise A+规范

    1. 一个 promise 必须有3个状态,pending,fulfilled(resolved),rejected。pending 状态可以转到 fulfilled(resolved)或者rejected状态。当处于fulfilled(resolved)状态或者rejected状态的时候,状态就不可变了;

    2. 一个promise必须有一个then方法,then方法接受两个参数:
      promise.then(onFulfilled,onRejected)
      其中 onFulfilled 方法表示状态从pending——>fulfilled(resolved)时所执行的方法,而onRejected 方法表示状态从pending——>rejected时所执行的方法;

    3. 为了实现链式调用,then 方法必须返回一个 promise
      promise2 = promise1.then(onFulfilled,onRejected)

    参考:https://promisesaplus.com/

    (3)实现一个 Promise

    • v1.0

    const STATUS = {
      resolved: "resolved",
      rejected: "rejected",
      pending: "pending"
    };
    
    class MyPromise {
      constructor(constructor) {
        this.status = STATUS.pending; //定义状态改变前的初始状态
        this.value = undefined; //定义状态为resolved的时候的状态
        this.reason = undefined; //定义状态为rejected的时候的状态
        this.resolve = this.resolve.bind(this);
        this.reject = this.reject.bind(this);
        this.then = this.then.bind(this);
        //捕获构造异常
        try {
          constructor(this.resolve, this.reject);
        } catch (e) {
          this.reject(e);
        }
      }
      resolve(value) {
        if (this.status === STATUS.pending) {
          this.value = value;
          this.status = STATUS.resolved;
        }
      }
      reject(reason) {
        if (this.status === STATUS.pending) {
          this.reason = reason;
          this.status = STATUS.rejected;
        }
      }
      then(onFullfilled, onRejected) {
        if (this.status === STATUS.resolved) {
          onFullfilled(this.value);
        } else if (this.status === STATUS.rejected) {
          onRejected(this.reason);
        }
      }
    }
    

    不足:异步执行resolve时无输出,因为 then 函数会先执行,此时的状态依然是 pending

    var p = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        resolve(1);
      }, 1000);
    });
    p.then(
      success => {
        console.log("fufilled:", success);
      }
    ); //无输出
    
    • v2.0(处理异步)

    为了处理异步逻辑,用2个数组 onFullfilledArray 和 onRejectedArray 来保存状态改变后要执行的方法。在状态发生改变时,在 resolve(reject)中一次遍历执行数组中的方法

    class MyPromise {
      constructor(constructor) {
        this.status = STATUS.pending; //定义状态改变前的初始状态
        this.value = undefined; //定义状态为resolved的时候的状态
        this.reason = undefined; //定义状态为rejected的时候的状态
    
        this.onFullfilledArray = [];
        this.onRejectedArray = [];
    
        this.resolve = this.resolve.bind(this);
        this.reject = this.reject.bind(this);
        this.then = this.then.bind(this);
        //捕获构造异常
        try {
          constructor(this.resolve, this.reject);
        } catch (e) {
          this.reject(e);
        }
      }
      resolve(value) {
        if (this.status === STATUS.pending) {
          this.value = value;
          this.status = STATUS.resolved;
          this.onFullfilledArray.forEach(onFullfilled => {
            onFullfilled(this.value);
          });
        }
      }
      reject(reason) {
        if (this.status === STATUS.pending) {
          this.reason = reason;
          this.status = STATUS.rejected;
          this.onRejectedArray.forEach(onRejected => {
            onRejected(this.reason);
          });
        }
      }
      then(onFullfilled, onRejected) {
        if (this.status === STATUS.pending) {
          this.onFullfilledArray.push(onFullfilled);
          this.onRejectedArray.push(onRejected);
        } else if (this.status === STATUS.resolved) {
          onFullfilled(this.value);
        } else if (this.status === STATUS.rejected) {
          onRejected(this.reason);
        }
      }
    }
    

    不足:没有实现链式调用。Promise/A+规范的最大的特点就是链式调用,也就是说then方法返回的应该是一个promise

    new Promise((resolve, reject) => {
        resolve(1);
    })
    .then((value) => {
        console.log("v1",value);
        return value + 1;
    })
    .then((value) => {
        console.log("v2",value);
    }); 
    //v1 1
    //v2 2
    
    • v3.0(链式调用)

    class MyPromise {
      constructor(constructor) {
        this.status = STATUS.pending; //定义状态改变前的初始状态
        this.value = undefined; //定义状态为resolved的时候的状态
        this.reason = undefined; //定义状态为rejected的时候的状态
    
        this.onFullfilledArray = [];
        this.onRejectedArray = [];
    
        this.resolve = this.resolve.bind(this);
        this.reject = this.reject.bind(this);
        this.then = this.then.bind(this);
        //捕获构造异常
        try {
          constructor(this.resolve, this.reject);
        } catch (e) {
          this.reject(e);
        }
      }
      resolve(value) {
        if (this.status === STATUS.pending) {
          this.value = value;
          this.status = STATUS.resolved;
          this.onFullfilledArray.forEach(onFullfilled => {
            onFullfilled(this.value);
          });
        }
      }
      reject(reason) {
        if (this.status === STATUS.pending) {
          this.reason = reason;
          this.status = STATUS.rejected;
          this.onRejectedArray.forEach(onRejected => {
            onRejected(this.reason);
          });
        }
      }
      then(onFullfilled, onRejected) {
        let promise2 = null;
        let self = this;
        if (this.status === STATUS.pending) {
          promise2 = new MyPromise(function(resolve, reject) {
            self.onFullfilledArray.push(function() {
              try {
                resolve(onFullfilled(self.value));
              } catch (e) {
                reject(e); //error catch
              }
            });
            self.onRejectedArray.push(function() {
              try {
                reject(onRejected(self.reason));
              } catch (e) {
                reject(e); // error catch
              }
            });
          });
        } else if (this.status === STATUS.resolved) {
          let value = this.value;
          promise2 = new MyPromise(function(resolve, reject) {
            try {
              //将上次一then里面的方法传递进下一个Promise的状态
              resolve(onFullfilled(value));
            } catch (e) {
              console.log("err", e);
              reject(e); //error catch
            }
          });
        } else if (this.status === STATUS.rejected) {
          let reason = this.reason;
          promise2 = new MyPromise(function(resolve, reject) {
            try {
              //将then里面的方法传递到下一个Promise的状态里
              reject(onRejected(reason));
            } catch (e) {
              reject(e);
            }
          });
        }
        return promise2;
      }
    }
    

    不足:then函数里面的onFullfilled方法和onRejected方法的返回值可以是对象,函数,甚至是另一个promise

    • v4.0 (then函数中onFullfilled和onRejected方法的返回值问题)

    ......
    参考:https://github.com/forthealllight/blog/issues/4


 

Copyright © 2018 bbs.dian.org.cn All rights reserved.

与 Dian 的连接断开,我们正在尝试重连,请耐心等待