Promise/A+规范 Promise 规范有 Promise/A Promise/B Promise/C Promise/D Promise/A+是 Promise/A 的升级版本 Promise 有 3 个状态:等待态(Pending)、执行态(Fulfilled)、拒绝态(Rejected) then 方法可以被一个 promise 调用多次,then 方法必须返回一个 promise 等…

Promise/A+规范

  1. Promise 规范有 Promise/A Promise/B Promise/C Promise/D
  2. Promise/A+是 Promise/A 的升级版本
  3. Promise 有 3 个状态:等待态(Pending)、执行态(Fulfilled)、拒绝态(Rejected)
  4. then 方法可以被一个 promise 调用多次,then 方法必须返回一个 promise

等待态(Pending)可以迁移到执行态(Fulfilled)或者拒绝态(Rejected)

执行态(Fulfilled)不可迁移到其他任务状态,必须拥有不可变的终值

拒绝态(Rejected)不可迁移到其他任务状态,必须拥有一个不可变的据因

实现的功能

  1. Promise.prototype.then
  2. Promise.prototype.catch
  3. Promise.resolve
  4. Promise.reject
  5. Promise.all
  6. Promise.race
  7. Promise.finally

如果对 Promise 方法不熟悉,可以看阮一峰老师教程

简单实现

function PromiseCopy(fn) {
  // 定义一个then,用于把then的回调函数,是一个函数
  this.then = (cb) => {
    this.cb = cb;
  };
  // 定义一个resolve,是一个函数,用于执行then中回调函数
  this.resolve = (data) => {
    this.cb(data);
  };
  // 把this.resolve作为fn回调函数
  fn(this.resolve);
}

var promise = new PromiseCopy((resolve) => {
  setTimeout(() => {
    resolve('hello world');
  }, 1000);
});
promise.then((result) => {
  console.log(result);
});

完整实现的关键点

  1. 构造函数必须接受一个函数作为参数
  2. Promise 对象存在三种状态:PENDING、FULFILLED、REJECTED
  3. 状态的改变是单向的,也就是说只能由 PENDING->FULFILLED 或 FULFILLED->FULFILLED
  4. then 方法可以被多次调用,且必须返回一个 promise,当执行 then 方法的回调函数时,把回调函数 push 到队列中,当 resolve 或 reject 方法执行的时候,依次执行队列中函数,并清空队列,实现 then 方法的多次调用
switch (_status) {
  // 当状态为PENDING,将then方法回调函数加入执行队列
  case PENDING:
    this._fulfilledQueues.push(fulfilled);
    this._rejcetedQueues.push(rejected);
    break;
  // 如果是FULFILLED,执行成功时执行的回调函数
  case FULFILLED:
    fulfilled(_value);
    break;
  // 如果是REJECTED,执行失败时执行的回调函数
  case REJECTED:
    rejected(_value);
    break;
}
// 依次执行成功队列中的函数,直到队列中的函数执行完毕
const runFulfilled = (value) => {
  let cb;
  while ((cb = this._fulfilledQueues.shift())) {
    cb(value);
  }
};
// 依次执行失败队列的函数,直到队列中的函数执行完毕
const runReject = (error) => {
  let cb;
  while (cb == this._rejcetedQueues.shift()) {
    cb(error);
  }
};
  1. resolve 方法传入的参数是一个 Promise 时,则参数的状态决定当前 Promise 状态,这就需要判断参数如果是 promise,先等待参数(promise)状态改变后,再去执行下一个 then 的回调函数
// 成功时执行的函数
let fulfilled = (value) => {
  try {
    // 如果then方法传入的参数onFulfilled不是一个函数,直接执行promise的resolve方法
    if (!isFunction(onFulfilled)) {
      onFulfilledNext(value);
    } else {
      // 否则就执行onFulfilled回调函数
      let res = onFulfilled(value);
      // 如果onFulfilled回调函数的结果是一个Promise
      if (res instanceof MyPromise) {
        // 必须等待状态改变后,再去执行promise的resolve方法
        res.then(onFulfilledNext, onRejectedNext);
      } else {
        // 如果onFulfilled回调函数的结果不是一个Promise,直接执行promise的resolve方法
        onFulfilledNext(res);
      }
    }
  } catch (error) {
    // 如果函数执行出错,更新一下任务状态
    onRejectedNext(error);
  }
};

完整实现代码

// 构造函数Promise必须接受一个函数作为参数,写一个方法,用户判断是否是函数
let isFunction = (fn) => {
  return typeof fn === 'function';
};
// 定义三种状态
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
// myPromise 构造函数,接收一个函数作为参数
class MyPromise {
  constructor(handle) {
    if (!isFunction(handle)) {
      throw new Error('MyPromise 必须传入一个函数');
    }
    // 初始化状态
    this._status = PENDING;
    // 初始化传递值
    this._value = undefined;
    // 添加成功回调函数队列
    this._fulfilledQueues = [];
    // 添加失败回调函数队列
    this._rejcetedQueues = [];
    try {
      // 执行handle
      handle(this._resolve.bind(this), this._reject.bind(this));
    } catch (error) {
      this._reject(error);
    }
  }
  // 添加resolve时执行的函数
  _resolve(val) {
    // run方法
    const run = () => {
      // 如果状态不是PENDING状态,返回
      if (this._status != PENDING) return;
      // 依次执行成功队列中的函数,直到队列中的函数执行完毕
      const runFulfilled = (value) => {
        let cb;
        while ((cb = this._fulfilledQueues.shift())) {
          cb(value);
        }
      };
      // 依次执行失败队列的函数,直到队列中的函数执行完毕
      const runReject = (error) => {
        let cb;
        while (cb == this._rejcetedQueues.shift()) {
          cb(error);
        }
      };
      // 如果resolve中的参数是一个Promise对象,则必须等待这个Promise状态改变后,才去依次执行队列中的函数
      // 当前Promise的状态才会改变,状态的改变取决于当前当前Promise的状态
      if (val instanceof MyPromise) {
        val.then(
          (value) => {
            this._value = value;
            this._status = FULFILLED;
            runFulfilled(value);
          },
          (err) => {
            this._value = err;
            this._status = REJECTED;
            runReject(err);
          }
        );
      } else {
        // 如果resolve不是一个Promise对象,则依次执行成功队列中的函数
        this._value = val;
        this._status = FULFILLED;
        runFulfilled(val);
      }
    };
    // 异步执行run方法
    setTimeout(run, 0);
  }
  // 添加reject时执行的函数
  _reject(error) {
    // 如果状态是PENDING,返回
    if (this._status != PENDING) return;
    // run方法
    const run = () => {
      this._status = REJECTED;
      this._value = error;
      let cb;
      // 依次执行失败队列的中的函数,直到执行到最后一个
      while ((cb = this._rejcetedQueues.shift())) {
        cb(error);
      }
    };
    // 异步执行run方法
    setTimeout(run, 0);
  }
  // 添加then方法
  then(onFulfilled, onRejected) {
    // 获取到当前状态
    const { _value, _status } = this;
    // then方法返回一个Promise
    return new MyPromise((onFulfilledNext, onRejectedNext) => {
      // 成功时执行的函数
      let fulfilled = (value) => {
        try {
          // 如果then方法传入的参数onFulfilled不是一个函数,直接执行promise的resolve方法
          if (!isFunction(onFulfilled)) {
            onFulfilledNext(value);
          } else {
            // 否则就执行onFulfilled回调函数
            let res = onFulfilled(value);
            // 如果onFulfilled回调函数的结果是一个Promise
            if (res instanceof MyPromise) {
              // 必须等待状态改变后,再去执行promise的resolve方法
              res.then(onFulfilledNext, onRejectedNext);
            } else {
              // 如果onFulfilled回调函数的结果不是一个Promise,直接执行promise的resolve方法
              onFulfilledNext(res);
            }
          }
        } catch (error) {
          // 如果函数执行出错,更新一下任务状态
          onRejectedNext(error);
        }
      };
      // 失败时执行的函数
      let rejected = (error) => {
        try {
          // 如果then方法传入的参数onRejected不是一个函数,直接执行promise的resolve方法
          if (!isFunction(onRejected)) {
            onRejectedNext(error);
          } else {
            // 否则就执行onRejected函数
            let res = onRejected(error);
            // 如果onRejected函数的结果是一个Promise
            if (res instanceof MyPromise) {
              // 必须等待状态改变后,再去执行promise的resolve方法
              res.then(onFulfilledNext, onRejectedNext);
            } else {
              // 如果onRejected函数的结果不是一个Promise,直接执行promise的resolve方法
              onRejectedNext(error);
            }
          }
        } catch (error) {
          onRejectedNext(error);
        }
      };
      switch (_status) {
        // 当状态为PENDING,将then方法回调函数加入执行队列
        case PENDING:
          this._fulfilledQueues.push(fulfilled);
          this._rejcetedQueues.push(rejected);
          break;
        // 如果是FULFILLED,执行成功时执行的回调函数
        case FULFILLED:
          fulfilled(_value);
          break;
        // 如果是REJECTED,执行失败时执行的回调函数
        case REJECTED:
          rejected(_value);
          break;
      }
    });
  }
  // catch方法,catch方法实际上返回的是then,只不过只传入了Rejected状态的回调函数
  catch(onRejected) {
    return this.then(undefined, onRejected);
  }
  // 静态方法:resolve
  static resolve(value) {
    // 如果resolve传入的值是一个Promise,直接返回这个实例
    if (value instanceof MyPromise) return value;
    // 否则,就执行promise的resolve方法
    return new MyPromise((resolve) => resolve(value));
  }
  // 静态方法:reject
  static reject(value) {
    // 执行promise的reject方法
    return new MyPromise((resolve, reject) => reject(value));
  }
  // 静态方法:all
  // all方法接收一个数组,数组的成员都是promise实例
  // 返回一个promise实例,这个promise的状态取决于数组成员状态
  // 只有成员都变成了fulfilled,当前promise的状态才会变成fullfilled
  // 只要有一个成员的状态变成了rejected,当前promise的状态变成了rejected,第一个被rejected的成员的值传递给当前promise
  static all(list) {
    // console.log(list)
    return new MyPromise((resolve, reject) => {
      let values = [];
      let count = 0;
      for (let [i, p] of list.entries()) {
        this.resolve(p).then(
          (res) => {
            values[i] = res;
            count++;
            if (count == list.length) resolve(values);
          },
          (err) => {
            reject(err);
          }
        );
      }
    });
  }
  // 静态方法:race
  // race方法接收一个数组,数组的成员都是promise实例
  // 返回一个promise,promise 的状态取决于数组成员状态
  // 只要有一个成员的状态变化了,那么当前promise的状态就会变化,第一个变化的返回值传递给当前promise
  static race(list) {
    return new MyPromise((reslove, reject) => {
      for (let p of list) {
        this.resolve(p).then(
          (res) => {
            reslove(res);
          },
          (err) => {
            reject(err);
          }
        );
      }
    });
  }
  // finally:不管promise是什么状态,在执行完then或catch指定的回调函数,都会执行finally方法执行的回调函数
  // 本质是then方法的特例
  finally(cb) {
    return this.then(
      (value) => MyPromise.reslove(cb()).then(() => value),
      (error) =>
        MyPromise.resolve(cb()).then(() => {
          throw error;
        })
    );
  }
}

使用

// then方法
var promise = new MyPromise((resolve, reject) => {
  setTimeout(function() {
    resolve('promise');
  }, 1000);
});
promise.then(
  (res) => {
    console.log(res);
  },
  (error) => {
    console.log(error);
  }
);
// catch方法
var promise2 = new MyPromise((resolve, reject) => {
  setTimeout(function() {
    reject(new Error('ERROR'));
  }, 1000);
});
promise2.catch((error) => {
  console.log(error);
});
// 静态方法resolve
var promise3 = MyPromise.resolve('promise3');
promise3.then((res) => {
  console.log(res);
});
// 静态方法reject
var promise4 = MyPromise.reject(new Error('ERROR'));
promise4.then(null, (error) => {
  console.log(error);
});
// 静态方法all:有一个状态变成了rejected,promise状态就会变成reject,promise2状态是rejected
var promise5 = MyPromise.all([promise, promise2]);
promise5.then(
  (res) => {
    console.log(123123);
  },
  (err) => {
    console.log(err);
  }
);
// 静态方法all:所有状态变成fullfilled,promise状态就会变成fullfilled
var promise6 = MyPromise.all([promise, promise]);
promise6.then(
  (res) => {
    console.log(123123);
  },
  (err) => {
    console.log(err);
  }
);
// finally方法
var promise7 = new Promise((reslove, reject) => {
  reslove('promise7');
});
promise7
  .then(
    (res) => {
      console.log(res);
    },
    (error) => {}
  )
  .finally((value) => {
    console.log('我是fanilly,但是我不知道当前promise状态');
  });
// resolve中传入一个promise对象
var promise8 = new Promise((reslove, reject) => {
  reslove(promise7);
});
promise8.then((res) => {
  console.log('resolve中传入一个promise对象', res);
});

参考

3 行代码实现一个简易版

Promises/A+规范

Promise 实现原理(附源码)

暂无评论