自己实现一个Promise

功能清单:

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

具体实现

function Promise(fn) {
    var _this = this; 
    var callback = null;
    this._value = null; // 存放 $A 的resolve(解决)的结果
    this._reason = null; // 存放 $A 的reject(拒绝)的原因
    this._thenCallbacks = []; // 存放resolve前调用then时传入的函数(可能多次调用then,所以是数组)
    this._catchCallbacks = []; // 存放reject前调用catch时传入的函数(可能多次调用catch,所以是数组)
    this._status = "pending";

    function onResolved(val) {
      if (_this._status !== 'pending') { // 若status已经改变为"resolved"或"rejected",回调在then内处理
        return
      }
      setTimeout(function () {
        // 确保回调是异步执行的的
        _this._value = val;
        _this._status = "resolved";
        while (callback = _this._thenCallbacks.shift()) { // 按注册顺序依次执行回调
          callback(val)
        }
      }, 0);
    }

    function onRejected(reason) {
      if (_this._status !== 'pending') {
        return
      }
      setTimeout(function () {
        _this._reason = reason;
        _this._status = "rejected";
        while (callback = _this._catchCallbacks.shift()) {
          callback(reason)
        }
      }, 0);
    }

    fn(onResolved, onRejected);
  }

重点

  Promise.prototype.then = function (onResolved, onRejected) { 
    var _this = this  // 本次Promise(命名为$A)

    return new Promise(function (resolve, reject) { /* then始终返回一个Promise(命名为$B),用于链式调用: new Promise( ... ).then( ... ).then( ... )  */

      function resolveHandle(value) { // 属于 $A
        var ret = (typeof onResolved === "function" && onResolved(value)) || value; 

        if (ret && ret instanceof Promise) { // 如果 ret为Promise实例(命名为$C)
          ret.then(function (value) {
            resolve(value); // 调用$B的resolve, 将 $C 的结果值传给 $B,也就是说下一个then中的回调可以获取到 $C 的结果值
          }, function (reason) {
            reject(reason)
          });

        } else {  如果 ret 不是为Promise实例
          resolve(ret); // 调用$B的resolve, 将 ret 传给 $B,也就是说下一个then中的回调可以获取到ret
        }
      }

      function rejectHandle(reason) {  // 属于 $A
        var err = (typeof onRejected === "function" && onRejected(reason)) || reason;
        reject(err);  // 调用$B的reject
      }

      if (_this._status === "pending") {
        // resolve或reject前调用then
        _this._thenCallbacks.push(resolveHandle);
        _this._catchCallbacks.push(rejectHandle);

      } else if (_this._status === "resolved") {
        // 状态改变后的then操作,立刻执行
        resolveHandle(_this._value)
      } else if (_this._status === "rejected") {
        rejectHandle(_this._reason);
      }
    });
  };
  Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected)
  }
  Promise.resolve = function (value) {
    return new Promise(function (resolve, reject) {
      resolve(value)
    })
  }
  Promise.reject = function (reason) {
    return new Promise(function (resolve, reject) {
      reject(reason)
    })
  }
  Promise.all = function (promises) {
    if (!Array.isArray(promises)) {
      throw new TypeError('必须传入promise数组');
    }
    var length = promises.length
    var values = []

    return new Promise(function (resolve, reject) {
      function rejectHandle(reason) {
        reject(reason) // 只要其中一个reject,整体reject
      }

      function resolveHandle(index) {
        return function (value) {
          values[index] = value // 按传入时的顺序记录每个promise的结果值
          if (--length === 0) { // 所有子promise都resolve后,整体resolve
            resolve(values)
          }
        }
      }
      
      promises.forEach(function (item, index) {
        item.then(resolveHandle(index), rejectHandle)
      })
    })
  }
  Promise.race = function (promises) {
    if (!Array.isArray(promises)) {
      throw new TypeError('必须传入promise数组');
    }
    return new Promise(function (resolve, reject) {
      function rejectHandle(reason) {
        reject(reason)
      }

      function resolveHandle(value) {
        resolve(value)
      }
      promises.forEach(function (item) {
        item.then(resolveHandle, rejectHandle)
      })
    })
  }
  // 不管resolved还是rejected,都会执行,避免同样的语句需要在then()和catch()中各写一次的情况。
  Promise.prototype.finally = function (callback) { 
    return this.then(callback, callback)
  }

使用 UMD 规范封装:

(function (global, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD
    define(factory)
  } else if (typeof exports === 'object' && typeof module !== 'undefined') {
    // CommonJS (如node)
    module.exports = factory()
  } else {
    // 浏览器全局变量
    global.promisePolyfill = factory()
  }
})(this, function () {
  'use strict';
   /*
      定义Promise的代码
   */  

  function promisePolyfill () {
    var global = null
    try {
      global = Function('return this')();
    } catch (e) {
      throw new Error('全局对象不可用');
    }
    global.Promise = Promise
  }
  return promisePolyfill
})

使用

promisePolyfill()  // 注册Promise全局变量

Prmoises A+规范

猜你喜欢

转载自www.cnblogs.com/JRliu/p/9211611.html
今日推荐