Promise源码

281 阅读4分钟

摄图网_401025654_与鲸鱼在云层嬉戏的女孩(非企业商用).jpg

ES6只给出了Promise A+规范,实际上的Promise都是由各浏览器厂商实现的,我们今天自己写一个符合Promise A+规范的Promise

一、总览

image.png

二、基础版本

const PENDING = 'pending';
const FULFILED = 'fulfiled';
const REJECTED = 'rejected';

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

    const resolve = (value) => {
      if (this.status === PENDING) {
        this.status = FULFILED;
        this.value = value;
      }
    }

    const reject = (reason) => {
      if (this.status === PENDING) {
        this.status = REJECTED;
        this.reason = reason;
      }
    }

    try {
      executor(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }

  then(onFulfiled, onRejected) {
    if (this.status === FULFILED) {
      setTimeout(() => {
        onFulfiled(this.value)
      })
    } else if (this.status === REJECTED) {
      setTimeout(() => {
        onRejected(this.reason)
      })
    }
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }
}
// 测试then
// 输出:1
const p = new Promise((resolve, reject) => {
  reject(1);
}).then(data => {
  console.log(data);
}, err => {
  console.log(err);
})
// 测试catch
// 输出:1
const p = new Promise((resolve, reject) => {
  reject(1);
}).catch(err => {
  console.log(err)
})

三、链式调用

const PENDING = 'pending';
const FULFILED = 'fulfiled';
const REJECTED = 'rejected';

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

    const resolve = (value) => {
      if (this.status === PENDING) {
        this.status = FULFILED;
        this.value = value;
      }
    }

    const reject = (reason) => {
      if (this.status === PENDING) {
        this.status = REJECTED;
        this.reason = reason;
      }
    }

    try {
      executor(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }

  then(onFulfiled, onRejected) {
    const self = this;
    return new Promise((resolve, reject) => {
      if (self.status === FULFILED) {
        setTimeout(() => {
          try {
            onFulfiled(self.value)
          } catch (e) {
            reject(e);
          }
        })
      } else if (self.status === REJECTED) {
        setTimeout(() => {
          try {
            onRejected(self.reason);
          } catch (e) {
            reject(e);
          }
        })
      }
    })
  }

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

四、异步操作

const PENDING = 'pending';
const FULFILED = 'fulfiled';
const REJECTED = 'rejected';

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

    const resolve = (value) => {
      if (this.status === PENDING) {
        this.status = FULFILED;
        this.value = value;
        this.onFulfiledCallBacks.forEach(fn => fn());
      }
    }

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

    try {
      executor(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }

  then(onFulfiled, onRejected) {

    const self = this;
    return new Promise((resolve, reject) => {
      if (self.status === PENDING) {
        setTimeout(() => {
          try {
            self.onFulfiledCallBacks.push(() => {
              const res = onFulfiled(self.value);
              res instanceof Promise ? res.then(resolve, reject) : resolve(res);
            })
          } catch (e) {
            reject(e);
          }
        })

        setTimeout(() => {
          try {
            self.onRejectedCallBacks.push(() => {
              const res = onRejected(self.reason);
              res instanceof Promise ? res.then(resolve, reject) : resolve(res);
            })
          } catch (e) {
            reject(e);
          }
        })
      } else if (self.status === FULFILED) {
        setTimeout(() => {
          try {
            const res = onFulfiled(self.value);
            res instanceof Promise ? res.then(resolve, reject) : resolve(res);
          } catch (e) {
            reject(e);
          }
        })
      } else if (self.status === REJECTED) {
        setTimeout(() => {
          try {
            const res = onRejected(self.reason);
            res instanceof Promise ? res.then(resolve, reject) : resolve(res);
          } catch (e) {
            reject(e);
          }
        })
      }
    })
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }
}
// 测试
// 输出:
// Promise {
//  status: 'fulfiled',
//  value: 1000,
//  reason: undefined,
//  onFulfiledCallBacks: [],
//  onRejectedCallBacks: []
// }
  
const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1);
  }, 1000);
}).then(data => {
  return data*10;
}, err => {
  return err*10;
}).then(data => {
  return data*100;
}, err => {
  return err*100;
})

setTimeout(() => {
  console.log(p)
}, 2000);

五、值穿透

const PENDING = 'pending';
const FULFILED = 'fulfiled';
const REJECTED = 'rejected';

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

    const resolve = (value) => {
      if (this.status === PENDING) {
        this.status = FULFILED;
        this.value = value;
        this.onFulfiledCallBacks.forEach(fn => fn());
      }
    }

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

    try {
      executor(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }

  then(onFulfiled, onRejected) {
    onFulfiled = typeof onFulfiled === 'function' ? onFulfiled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => {
      throw new Error(reason instanceof Error ? reason.message : reason);
    }
    const self = this;
    return new Promise((resolve, reject) => {
      if (self.status === PENDING) {
        setTimeout(() => {
          try {
            self.onFulfiledCallBacks.push(() => {
              const res = onFulfiled(self.value);
              res instanceof Promise ? res.then(resolve, reject) : resolve(res);
            })
          } catch (e) {
            reject(e);
          }
        })

        setTimeout(() => {
          try {
            self.onRejectedCallBacks.push(() => {
              const res = onRejected(self.reason);
              res instanceof Promise ? res.then(resolve, reject) : resolve(res);
            })
          } catch (e) {
            reject(e);
          }
        })
      } else if (self.status === FULFILED) {
        setTimeout(() => {
          try {
            const res = onFulfiled(self.value);
            res instanceof Promise ? res.then(resolve, reject) : resolve(res);
          } catch (e) {
            reject(e);
          }
        })
      } else if (self.status === REJECTED) {
        setTimeout(() => {
          try {
            const res = onRejected(self.reason);
            res instanceof Promise ? res.then(resolve, reject) : resolve(res);
          } catch (e) {
            reject(e);
          }
        })
      }
    })
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }
}
// 测试
// 输出:
// Promise {
//  status: 'fulfiled',
//  value: 1,
//  reason: undefined,
//  onFulfiledCallBacks: [],
//  onRejectedCallBacks: []
// }

const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1);
  }, 1000);
}).then(222, 333);

setTimeout(() => {
  console.log(p)
}, 2000);

六、静态方法

  static resolve(value) {
    if (value instanceof Promise) {
      // 如果是Promise实例,直接返回
      return value;
    } else {
      // 如果不是Promise实例,返回一个新的Promise对象,状态为FULFILLED
      return new Promise((resolve, reject) => resolve(value));
    }
  }
  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason);
    })
  }
  static all(promiseArr) {
    const len = promiseArr.length;
    const values = new Array(len);
    // 记录已经成功执行的promise个数
    let count = 0;
    return new Promise((resolve, reject) => {
      for (let i = 0; i < len; i++) {
        // Promise.resolve()处理,确保每一个都是promise实例
        Promise.resolve(promiseArr[i]).then(
          val => {
            values[i] = val;
            count++;
            // 如果全部执行完,返回promise的状态就可以改变了
            if (count === len) resolve(values);
          },
          err => reject(err),
        );
      }
    })
  }
  static race(promiseArr) {
    return new Promise((resolve, reject) => {
      promiseArr.forEach(p => {
        Promise.resolve(p).then(
          val => resolve(val),
          err => reject(err),
        )
      })
    })
  }

七、完整代码

const PENDING = 'pending';
const FULFILED = 'fulfiled';
const REJECTED = 'rejected';

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

    const resolve = (value) => {
      if (this.status === PENDING) {
        this.status = FULFILED;
        this.value = value;
        this.onFulfiledCallBacks.forEach(fn => fn());
      }
    }

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

    try {
      executor(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }

  then(onFulfiled, onRejected) {
    onFulfiled = typeof onFulfiled === 'function' ? onFulfiled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => {
      throw new Error(reason instanceof Error ? reason.message : reason);
    }
    const self = this;
    return new Promise((resolve, reject) => {
      if (self.status === PENDING) {
        setTimeout(() => {
          try {
            self.onFulfiledCallBacks.push(() => {
              const res = onFulfiled(self.value);
              res instanceof Promise ? res.then(resolve, reject) : resolve(res);
            })
          } catch (e) {
            reject(e);
          }
        })

        setTimeout(() => {
          try {
            self.onRejectedCallBacks.push(() => {
              const res = onRejected(self.reason);
              res instanceof Promise ? res.then(resolve, reject) : resolve(res);
            })
          } catch (e) {
            reject(e);
          }
        })
      } else if (self.status === FULFILED) {
        setTimeout(() => {
          try {
            const res = onFulfiled(self.value);
            res instanceof Promise ? res.then(resolve, reject) : resolve(res);
          } catch (e) {
            reject(e);
          }
        })
      } else if (self.status === REJECTED) {
        setTimeout(() => {
          try {
            const res = onRejected(self.reason);
            res instanceof Promise ? res.then(resolve, reject) : resolve(res);
          } catch (e) {
            reject(e);
          }
        })
      }
    })
  }

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

  static resolve(value) {
    if (value instanceof Promise) {
      // 如果是Promise实例,直接返回
      return value;
    } else {
      // 如果不是Promise实例,返回一个新的Promise对象,状态为FULFILLED
      return new Promise((resolve, reject) => resolve(value));
    }
  }

  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason);
    })
  }

  static all(promiseArr) {
    const len = promiseArr.length;
    const values = new Array(len);
    // 记录已经成功执行的promise个数
    let count = 0;
    return new Promise((resolve, reject) => {
      for (let i = 0; i < len; i++) {
        // Promise.resolve()处理,确保每一个都是promise实例
        Promise.resolve(promiseArr[i]).then(
          val => {
            values[i] = val;
            count++;
            // 如果全部执行完,返回promise的状态就可以改变了
            if (count === len) resolve(values);
          },
          err => reject(err),
        );
      }
    })
  }

  static race(promiseArr) {
    return new Promise((resolve, reject) => {
      promiseArr.forEach(p => {
        Promise.resolve(p).then(
          val => resolve(val),
          err => reject(err),
        )
      })
    })
  }
}

八、参考

juejin.cn/post/686003…