Promise 介绍

什么是 Promise?解决哪些问题?

  • 回调天堂,代码不好保护,错误处理十分的麻烦,不能对立处理错误
  • 解决多个申请并发问题

ES6 将其写进了语言规范,对立了用法,原生提供了 Promise 对象。

  • Promise 是一个对象,应用的时候 new 即可
  • Promise 在 new 的时候传入一个执行器,即 executor,这个函数在 new Promise 时立刻执行
  • Promise 的 executor 函数有两个参数,一个是 resolve,一个是 reject。resolve 让 Promise 由 pending 期待态变成 fulfilled 胜利态,reject 让 Promise 由 pending 期待态变成 rejected 失败态。resolve 和 reject 是 Promise 提供的。
  • Promise 的 3 个状态:pending 期待态、fulfilled 胜利态、rejected 失败态
  • Promise 的 resolve 或者 reject 只能调用一次,一旦胜利之后不能再失败,一旦失败之后不能再胜利
  • 每个 Promise 实例有个 then() 办法,该办法外部传递两个函数,第一个是胜利回调函数,第二个是失败回调函数
  • 让一个 Promise 失败能够调用 reject,也能够抛出一个谬误
  • Promise 的 then() 办法返回的还是一个新的 Promise,所以 then() 之后还能够再 then

  // 定义三种状态  const REJECTED = 'REJECTED';  const FULFILLED = 'FULFILLED';  const PENDING = 'PENDING';  /**   * 判断一个变量是否是 Promise 的函数   * 1. 是否是对象并且不是 null   * 2. 是否有 then 属性并且 then 是一个办法   * @param {*} val    */  function isPromise(val) {    if (typeof val === 'object' && val !== null || typeof val === 'function') {      return typeof val.then === 'function';    }    return false;  }  console.log('--------------------- MY Promise ---------------------');  // 实现链式调用  /**   * 解决 then 中的胜利、失败回调函数返回值是否是 Promise 的状况   * @param {*} promise2 参见 Promise A+ 标准阐明 new Promise   * @param {*} x 是胜利、失败回调的返回值   */  const resolvePromise = (promise2, x) => {    const { resolve, reject } = promise2;    // 这里的判断是可能本人的 Promise 要和他人的 Promise 混用,可能不同的 Promise 库之间互相调用    // 如果 new 进去的 Promise2 和 x 是同一个,那么 x 永远不能胜利或者失败,所以卡死了,间接报错    if (promise2 === x) return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));    // 须要判断 x 的状态,判断 x 是不是 Promise    // 先判断是不是对象或者函数    if (typeof x === 'object' && x !== null || typeof x === 'function') {      let called; // 这里思考他人的 Promise 是否强壮,不强壮须要再判断一下,调用了胜利就不能失败,调用的失败就不能胜利。不能屡次调用胜利或者失败      try {        const then = x.then; // 外部可能抛出谬误        // 如果 then 不是函数就阐明是一个一般值,间接返回 x         if (typeof then !== 'function') resolve(x); // 比方:{ then: 'mhq' }        else {          // 这里不要再次调用 x.then 是避免取 then 的时候报错,万一 then 办法外面抛出了一个谬误呢?          then.call(x, y => {            if (called) return;            called = true;            // 如果 x 是一个 Promise,那么就持续解析胜利的值            resolvePromise(promise2, y);          }, f => {            if (called) return;            called = true;            reject(f); // 间接调用 r 作为失败的后果          });        }      } catch(err) {        if (called) return;        called = true;        reject(err);      }    } else {      resolve(x);    }  };  class Promise {    constructor(executor) {      // Promise 的状态      this.status = PENDING;      // 胜利后的值      this.value = undefined;      // 失败后的值      this.reason = undefined;      // 胜利回调函数,公布订阅      this.onResolvedCallbacks = [];      // 失败回调函数,公布订阅      this.onRejectedCallbacks = [];      /**       * Promise 外部提供的 resolve,让 Promise 的状态变成胜利态,并让胜利回调执行       * @param {*} value        */      const resolve = value => {        if (value instanceof Promise) {          return value.then(resolve, reject);        }        if (this.status === PENDING) {          this.status = FULFILLED;          this.value = value;          this.onResolvedCallbacks.forEach(fn => fn());        }      };      /**       * Promise 外部提供的 reject,让 Promise 的状态变成失败态,并让失败回调执行       * @param {*} reason        */      const reject = reason => {        if (this.status === PENDING) {          this.status = REJECTED;          this.reason = reason;          this.onRejectedCallbacks.forEach(fn => fn());        }      };      // try + catch 只能捕捉同步异样      try {        executor(resolve, reject);      } catch(err) {        reject(err);      }    }    // 只有 x 是一个一般值,就会让一个 Promise 变成胜利态    // 这个 x 有可能是一个 Promise,须要菜哟个这个 Promise 的状态    then(onFulfilled, onRejected) {      // 比方.then().then().then(() => {}); 这种调用,对可选参数的解决,透传      onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;      onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };      const promise2 = new Promise((resolve, reject) => { // 一旦 new 则立刻执行        if(this.status === FULFILLED) {          setTimeout(() => {            promise2.resolve = resolve;            promise2.reject = reject;            try {              const x = onFulfilled(this.value);              resolvePromise(promise2, x);            } catch (err) {              reject(err);            }          }, 0);        }        if (this.status === REJECTED) {          setTimeout(() => {            promise2.resolve = resolve;            promise2.reject = reject;            try {              const x = onRejected(this.reason);              resolvePromise(promise2, x);            } catch (err) {              reject(err);            }          }, 0);        }        if (this.status === PENDING) { // 自身是异步的          this.onResolvedCallbacks.push(() => {            setTimeout(() => { // 这里须要加上,不加上跑测试跑不通              promise2.resolve = resolve;              promise2.reject = reject;              try {                const x = onFulfilled(this.value);                resolvePromise(promise2, x);              } catch (err) {                reject(err);              }            });          });          this.onRejectedCallbacks.push(() => {            setTimeout(() => {              promise2.resolve = resolve;              promise2.reject = reject;              try {                const x = onRejected(this.reason);                resolvePromise(promise2, x);              } catch (err) {                reject(err);              }            });          });        }      });      return promise2;    }    /**     * Promise 中的 catch 指代的就是 then 没有胜利回调的一个别名而已     * @param {*} errCallback      */    catch(errCallback) {      return this.then(null, errCallback);    }  }  // 无论如何都会执行,把上一个 then 的后果向下传递,如果 finally 中返回了一个 Promise 会期待这个 Promise 执行实现后继续执行  Promise.prototype.finally = function(callback) {    return this.then(val => {      return Promise.resolve(callback()).then(() => val);    }, (err) => {      return Promise.resolve(callback()).then(() => { throw err; });    });  };  // npm install promises-aplus-tests -g  // promises-aplus-tests promise.js  // 测试本人写的 Promise 是否符合规范的包  Promise.deferred = () => {    const dfd = {};    dfd.promise = new Promise((resolve, reject) => {      dfd.resolve = resolve;      dfd.reject = reject;    });    return dfd;  };  /**   * Promise.resolve 他会期待外面的 Promise 执行胜利   * @param {*} val    */  Promise.resolve = val => {    return new Promise((resolve) => {      resolve(val);    });  };  /**   * Promise.reject 不会期待参数中的 Promise 执行结束   */  Promise.reject = () => {    return new Promise((_, reject) => {      reject(val);    });  };  /**   * Promise.all 办法示意期待所有的 Promise 全副胜利后才会执行回调,如果有一个 Promise 失败则 Promise 就失败了   * @param {*} promises    */  Promise.all = promises => {    return new Promise((resolve, reject) => {      const res = [];      let count = 0;      const resolveRes = (index, data) => {        res[index] = data;        if (++count === promises.length) {          resolve(res);        }      };      for(let i = 0; i < promises.length; i++) {        const current = promises[i];        if (isPromise(current)) {          current.then((data) => {            resolveRes(i, data);          }, (err) => {            reject(err);          });        } else {          resolveRes(i, current);        }      }    });  }  /**   * Promise.race 赛跑,谁是第一个实现的,就用他的后果,如果是失败这个 Promise 就失败,如果第一个是胜利就是胜利   * @param {*} promises    */  Promise.race = (promises) => {    return new Promise((resolve, reject) => {      for(let i = 0; i < promises.length; i++) {        let current = promises[i];        if (isPromise(current)) {          current.then(resolve, reject);        } else {          resolve(current);          break;        }      }    });  }  // 专门给 node 的 api 做的 promisify 办法,如 fs.readFile  Promise.promisify = fn => {    return (...arg) => {      return new Promise((resolve, reject) => {        fn(...arg, (err, data) => {          if (err) reject(err);          resolve(data);        });      });    }  };  module.exports = Promise;