Skip to content

手写Promise ​

实现思路:Promise源码实现 ​

  1. 模拟实现

    js
        // 模拟实现Promise
        // Promise利用三大手段解决回调地狱:
        // 1. 回调函数延迟绑定
        // 2. 返回值穿透
        // 3. 错误冒泡
    
        // 定义三种状态
        const PENDING = 'PENDING';      // 进行中
        const FULFILLED = 'FULFILLED';  // 已成功
        const REJECTED = 'REJECTED';    // 已失败
    
        class Promise {
          constructor(exector) {
            // 初始化状态
            this.status = PENDING;
            // 将成功、失败结果放在this上,便于then、catch访问
            this.value = undefined;
            this.reason = undefined;
            // 成功态回调函数队列
            this.onFulfilledCallbacks = [];
            // 失败态回调函数队列
            this.onRejectedCallbacks = [];
    
            const resolve = value => {
              // 只有进行中状态才能更改状态
              if (this.status === PENDING) {
                this.status = FULFILLED;
                this.value = value;
                // 成功态函数依次执行
                this.onFulfilledCallbacks.forEach(fn => fn(this.value));
              }
            }
            const reject = reason => {
              // 只有进行中状态才能更改状态
              if (this.status === PENDING) {
                this.status = REJECTED;
                this.reason = reason;
                // 失败态函数依次执行
                this.onRejectedCallbacks.forEach(fn => fn(this.reason))
              }
            }
            try {
              // 立即执行executor
              // 把内部的resolve和reject传入executor,用户可调用resolve和reject
              exector(resolve, reject);
            } catch(e) {
              // executor执行出错,将错误内容reject抛出去
              reject(e);
            }
          }
          then(onFulfilled, onRejected) {
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
            onRejected = typeof onRejected === 'function'? onRejected :
              reason => { throw new Error(reason instanceof Error ? reason.message : reason) }
            // 保存this
            const self = this;
            return new Promise((resolve, reject) => {
              if (self.status === PENDING) {
                self.onFulfilledCallbacks.push(() => {
                  // try捕获错误
                  try {
                    // 模拟微任务
                    setTimeout(() => {
                      const result = onFulfilled(self.value);
                      // 分两种情况:
                      // 1. 回调函数返回值是Promise,执行then操作
                      // 2. 如果不是Promise,调用新Promise的resolve函数
                      result instanceof Promise ? result.then(resolve, reject) : resolve(result);
                    })
                  } catch(e) {
                    reject(e);
                  }
                });
                self.onRejectedCallbacks.push(() => {
                  // 以下同理
                  try {
                    setTimeout(() => {
                      const result = onRejected(self.reason);
                      // 不同点:此时是reject
                      result instanceof Promise ? result.then(resolve, reject) : resolve(result);
                    })
                  } catch(e) {
                    reject(e);
                  }
                })
              } else if (self.status === FULFILLED) {
                try {
                  setTimeout(() => {
                    const result = onFulfilled(self.value);
                    result instanceof Promise ? result.then(resolve, reject) : resolve(result);
                  });
                } catch(e) {
                  reject(e);
                }
              } else if (self.status === REJECTED) {
                try {
                  setTimeout(() => {
                    const result = onRejected(self.reason);
                    result instanceof Promise ? result.then(resolve, reject) : resolve(result);
                  })
                } 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),
                )
              })
            })
          }
        }
  2. Promise.all

    • Promise.all是支持链式调用的,本质上就是返回了一个Promise实例,通过resolve和reject来改变实例状态。
      js
          Promise.myAll = function(promiseArr) {
            return new Promise((resolve, reject) => {
              const ans = [];
              let index = 0;
              for (let i = 0; i < promiseArr.length; i++) {
                promiseArr[i]
                .then(res => {
                  ans[i] = res;
                  index++;
                  if (index === promiseArr.length) {
                    resolve(ans);
                  }
                })
                .catch(err => reject(err));
              }
            })
          }
  3. Promise.race

    js
       Promise.race = function(promiseArr) {
          return new Promise((resolve, reject) => {
            promiseArr.forEach(p => {
              // 如果不是Promise实例需要转化为Promise实例
              Promise.resolve(p).then(
                val => resolve(val),
                err => reject(err),
              )
            })
          })
        }
  4. Promise并行限制

    • 就是实现有并行限制的Promise调度器问题。
      js
          class Scheduler {
            constructor() {
              this.queue = [];
              this.maxCount = 2;
              this.runCounts = 0;
            }
            add(promiseCreator) {
              this.queue.push(promiseCreator);
            }
            taskStart() {
              for (let i = 0; i < this.maxCount; i++) {
                this.request();
              }
            }
            request() {
              if (!this.queue || !this.queue.length || this.runCounts >= this.maxCount) {
                return;
              }
              this.runCounts++;
      
              this.queue.shift()().then(() => {
                this.runCounts--;
                this.request();
              });
            }
          }
            
          const timeout = time => new Promise(resolve => {
            setTimeout(resolve, time);
          })
            
          const scheduler = new Scheduler();
            
          const addTask = (time,order) => {
            scheduler.add(() => timeout(time).then(()=>console.log(order)))
          }
            
            
          addTask(1000, '1');
          addTask(500, '2');
          addTask(300, '3');
          addTask(400, '4');
          scheduler.taskStart()
          // 2
          // 3
          // 1
          // 4