zoukankan      html  css  js  c++  java
  • 【转】promise的实现

    原文:https://blog.csdn.net/sinat_17775997/article/details/70170939

    ----------------------------------------

    本文缘起前段时间一朋友换工作时,笔试题中要求手写一个Promise。在工作中虽已大量使用Promise,其原理却没有深入探究过,换做自己,当场也很难手写一个完善的Promise实现。近期补了一些课,以本文来彻底的理解Promise实现原理。

    http://www.jianshu.com/p/f8b052c71550

    1.Promise是什么

    Promise是抽象异步处理对象以及对其进行各种操作的组件,可以将复杂的异步处理轻松的进行模式化。
    使用Promise进行异步处理的一个例子

    1.  
      functiongetUserId() {
    2.  
      return new Promise(function (resolve, reject) {
    3.  
      // 异步请求
    4.  
      Y.io('/userid/1', {
    5.  
      on: {
    6.  
      success: function (id, res) {
    7.  
      var o = JSON.parse(res);
    8.  
      if (o.status === 1) {
    9.  
      resolve(o.id);
    10.  
      } else {
    11.  
      // 请求失败,返回错误信息
    12.  
      reject(o.errorMsg);
    13.  
      }
    14.  
      }
    15.  
      }
    16.  
      });
    17.  
      });
    18.  
      }
    19.  
       
    20.  
      getUserId().then(function (id) {
    21.  
      // do sth with id
    22.  
      }, function (error) {
    23.  
      console.log(error);
    24.  
      });

    如对Promise的使用尚不了解,推荐阅读JavaScript Promise Cookbook中文版

    ---------------------

    https://github.com/bruce-xu/Promise/blob/master/Promise.js

    /**
     * @file JS Promise实现
     * @author bruxexyj@gmail.com
     */
    (function (factory, global) {
        if (typeof define === 'function' && define.amd) {
            define(factory);
        }
        else if (typeof module === 'object' && module.exports) {
            module.exports = exports = factory();
        }
        else {
            global.Promise = factory();
        }
    }(function () {
    
        /**
         * Promise对象的内部状态
         *
         * @type {Object}
         */
        var Status = {
            PENDING: 'pending',
            FULLFILLED: 'resolved',
            REJECTED: 'rejected'
        };
    
        function empty() {}
    
        /**
         * Promise构造函数
         *
         * @constructor
         * @param {Function} resolver 此Promise对象管理的任务
         */
        function Promise(resolver) {
            // ES6原生的Promise构造函数中,若不通过`new`调用Promise的构造函数,会抛出TypeError异常。此处与其一致
            if (!(this instanceof Promise)) {
                throw new TypeError('TypeError: undefined is not a promise');
            }
    
            // ES6原生的Promise构造函数中,若无作为函数的resolver参数,会抛出TypeError异常。此处与其一致
            if (typeof resolver !== 'function') {
                throw new TypeError('TypeError: Promise resolver undefined is not a function');
            }
    
            /**
             * Promise对象内部的状态,初始为`pending`。状态只能由`pending`到`fullfilled`或`rejected`
             *
             * @type {string}
             */
            this._status = Status.PENDING;
    
            /**
             * Promise对象resolved/rejected后拥有的data/reason
             *
             *  - 此处保存此值是为了当一个Promise对象被resolved或rejected后,继续对其调用`then`添加任务,后续处理仍能获得当前Promise的值
             *
             * @type {Mixed}
             */
            this._value;
    
            /**
             * 当前Promise被resolved/rejected后,需处理的任务
             *
             *  - 由于同一个Promise对象可以调用多次`then`方法,以添加多个并行任务,所以此处是一个数组
             *
             * @type {Array.<Function>}
             */
            this._doneCallbacks = [];
            this._failCallbacks = [];
    
            var promise = this;
            resolver(
                function (data) {
                    resolve(promise, data);
                },
                function (reason) {
                    reject(promise, reason);
                }
            );
        }
    
        Promise.prototype = {
    
            constructor: Promise,
    
            /**
             * Promise的`then`方法
             *
             * @param {Function|Mixed} onResolve 当前Promise对象被resolved后,需处理的任务
             * @param {Function|Mixed} onReject 当前Promise对象被rejected后,需处理的任务
             * @return {Promise} 返回一个新的Promise对象,用于链式操作
             */
            then: function (onResolve, onReject) {
                var promise = new Promise(empty);
    
                this._doneCallbacks.push(makeCallback(promise, onResolve, 'resolve'));
                this._failCallbacks.push(makeCallback(promise, onReject, 'reject'));
    
                // 如果在一个已经被fullfilled或rejected的promise上调用then,则需要直接执行通过then注册的回调函数
                run(this);
    
                return promise;
            },
    
            /**
             * Promise的`done`方法
             *
             * @param {Function|Mixed} onResolve 当前Promise对象被resolved后,需处理的任务
             * @return {Promise} 返回一个新的Promise对象,用于链式操作
             */
            done: function (onResolve) {
                return this.then(onResolve, null);
            },
    
            /**
             * Promise的`fail`方法
             *
             * @param {Function|Mixed} onReject 当前Promise对象被rejected后,需处理的任务
             * @return {Promise} 返回一个新的Promise对象,用于链式操作
             */
            fail: function (onReject) {
                return this.then(null, onReject);
            },
    
            /**
             * Promise的`catch`方法
             *
             * @param {Function|Mixed} onFail 当前Promise对象被rejected后,需处理的任务
             * @return {Promise} 返回一个新的Promise对象,用于链式操作
             */
            catch: function (onFail) {
                return this.then(null, onFail);
            }
        };
    
        /**
         * 创建一个Promise对象,并用给定值resolve它
         *
         * @param {Mixed} value 用于resolve新创建的Promise对象的值
         * @return {Promise} 返回一个新的Promise对象,用于链式操作
         */
        Promise.resolve = function (value) {
            var promise = new Promise(empty);
            resolve(promise, value);
            return promise;
        };
    
        /**
         * 创建一个Promise对象,并用给定值reject它
         *
         * @param {Mixed} reason 用于reject新创建的Promise对象的值
         * @return {Promise} 返回一个新的Promise对象,用于链式操作
         */
        Promise.reject = function (reason) {
            var promise = new Promise(empty);
            reject(promise, reason);
            return promise;
        };
    
        /**
         * 返回一个promise,这个promise在iterable中的任意一个promise被解决或拒绝后,
         * 立刻以相同的解决值被解决或以相同的拒绝原因被拒绝
         *
         * @param {Iterable.<Promise|Mixed>} iterable 一组Promise对象或其它值
         * @return {Promise} 返回一个新的Promise对象,用于链式操作
         */
        Promise.race = function (iterable) {
            if (!iterable || !iterable.hasOwnProperty('length')) {
                throw new TypeError('TypeError: Parameter `iterable` must be a iterable object');
            }
    
            var promise = new Promise(empty);
            for (var i = 0, len = iterable.length; i < len; i++) {
                var iterate = iterable[i];
                if (!(iterate instanceof Promise)) {
                    iterate = Promise.resolve(iterate);
                }
    
                iterate.then(resolveRaceCallback, rejectRaceCallback);
            }
    
            var settled = false;
    
            function resolveRaceCallback(data) {
                if (settled) {
                    return;
                }
    
                settled = true;
                resolve(promise, data);
            }
    
            function rejectRaceCallback(reason) {
                if (settled) {
                    return;
                }
    
                settled = true;
                reject(promise, reason);
            }
        };
    
        /**
         * 返回一个promise,该promise会在iterable参数内的所有promise都被解决后被解决
         *
         * @param {Iterable.<Promise|Mixed>} iterable 一组Promise对象或其它值
         * @return {Promise} 返回一个新的Promise对象,用于链式操作
         */
        Promise.all = function (iterable) {
            if (!iterable || !iterable.hasOwnProperty('length')) {
                throw new TypeError('TypeError: Parameter `iterable` must be a iterable object');
            }
    
            var promise = new Promise(empty);
            var length = iterable.length;
            for (var i = 0; i < length; i++) {
                var iterate = iterable[i];
                if (!(iterate instanceof Promise)) {
                    iterate = Promise.resolve(iterate);
                }
    
                iterate.then(makeAllCallback(iterate, i, 'resolve'), makeAllCallback(iterate, i, 'reject'));
            }
    
            var result = [];
            var count = 0;
    
            function makeAllCallback(iterate, index, action) {
                return function (value) {
                    if (action === 'reject') {
                        reject(promise, value);
                        return;
                    }
    
                    result[index] = value;
    
                    if (++count === length) {
                        resolve(promise, result);
                    }
                }
            }
        };
    
        /**
         * 返回一个Deferred对象,包含一个新创建的Promise对象,以及`resolve`和`reject`方法
         *
         * @return {Deferred}
         */
        Promise.defer = function () {
            var promise = new Promise(empty);
    
            return {
                promise: promise,
                resolve: function (data) {
                    resolve(promise, data);
                },
                reject: function (reason) {
                    reject(promise, reason);
                }
            };
        };
    
        function run(promise) {
            // `then`方法中也会调用,所以此处仍需做一次判断
            if (promise._status === Status.PENDING) {
                return;
            }
    
            var value = promise._value;
            var callbacks = promise._status === Status.FULLFILLED
                ? promise._doneCallbacks
                : promise._failCallbacks;
    
            // Promise需要异步操作
            setTimeout(function () {
                for (var i = 0, len = callbacks.length; i < len; i++) {
                    callbacks[i](value);
                }
            });
    
            // 每个promise只能被执行一次。虽然`_doneCallbacks`和`_failCallbacks`用户不应该直接访问,
            // 但还是可以访问到,保险起见,做清空处理。
            promise._doneCallbacks = [];
            promise._failCallbacks = [];
        }
    
        function resolve(promise, data) {
            if (promise._status !== Status.PENDING) {
                return;
            }
    
            promise._status = Status.FULLFILLED;
            promise._value = data;
    
            run(promise);
        }
    
        function reject(promise, reason) {
            if (promise._status !== Status.PENDING) {
                return;
            }
    
            promise._status = Status.REJECTED;
            promise._value = reason;
    
            run(promise);
        }
    
        function makeCallback(promise, callback, action) {
            return function promiseCallback(value) {
                // 如果传递了callback,则使用前一个promise传递过来的值作为参数调用callback,
                // 并根据callback的调用结果来处理当前promise
                if (typeof callback === 'function') {
                    var x;
                    try {
                        x = callback(value);
                    }
                    catch (e) {
                        // 如果调用callback时抛出异常,则直接用此异常对象reject当前promise
                        reject(promise, e);
                    }
    
                    // 如果callback的返回值是当前promise,为避免造成死循环,需要抛出异常
                    // 根据Promise+规范,此处应抛出TypeError异常
                    if (x === promise) {
                        var reason = new TypeError('TypeError: The return value could not be same with the promise');
                        reject(promise, reason);
                    }
                    // 如果返回值是一个Promise对象,则当返回的Promise对象被resolve/reject后,再resolve/reject当前Promise
                    else if (x instanceof Promise) {
                        x.then(
                            function (data) {
                                resolve(promise, data);
                            },
                            function (reason) {
                                reject(promise, reason);
                            }
                        );
                    }
                    else {
                        var then;
                        (function resolveThenable(x) {
                            // 如果返回的是一个Thenable对象(此处逻辑有点坑,参照Promise+的规范实现)
                            if (x && (typeof x === 'object'|| typeof x === 'function')) {
                                try {
                                    then = x.then;
                                }
                                catch (e) {
                                    reject(promise, e);
                                    return;
                                }
    
                                if (typeof then === 'function') {
                                    // 调用Thenable对象的`then`方法时,传递进去的`resolvePromise`和`rejectPromise`方法(及下面的两个匿名方法)
                                    // 可能会被重复调用。但Promise+规范规定这两个方法有且只能有其中的一个被调用一次,多次调用将被忽略。
                                    // 此处通过`invoked`来处理重复调用
                                    var invoked = false;
                                    try {
                                        then.call(
                                            x,
                                            function (y) {
                                                if (invoked) {
                                                    return;
                                                }
                                                invoked = true;
    
                                                // 避免死循环
                                                if (y === x) {
                                                    throw new TypeError('TypeError: The return value could not be same with the previous thenable object');
                                                }
    
                                                // y仍有可能是thenable对象,递归调用
                                                resolveThenable(y);
                                            },
                                            function (e) {
                                                if (invoked) {
                                                    return;
                                                }
                                                invoked = true;
    
                                                reject(promise, e);
                                            }
                                        );
                                    }
                                    catch (e) {
                                        // 如果`resolvePromise`和`rejectPromise`方法被调用后,再抛出异常,则忽略异常
                                        // 否则用异常对象reject此Promise对象
                                        if (!invoked) {
                                            reject(promise, e);
                                        }
                                    }
                                }
                                else {
                                    resolve(promise, x);
                                }
                            }
                            else {
                                resolve(promise, x);
                            }
                        }(x));
                    }
                }
                // 如果未传递callback,直接用前一个promise传递过来的值resolve/reject当前Promise对象
                else {
                    action === 'resolve'
                        ? resolve(promise, value)
                        : reject(promise, value);
                }
            };
        }
    
        return Promise;
    }, this));
    

      

    /**
      * @file JS Promise实现
      * @author bruxexyj@gmail.com
      */
      (function (factory, global) {
      if (typeof define === 'function' && define.amd) {
      define(factory);
      }
      else if (typeof module === 'object' && module.exports) {
      module.exports = exports = factory();
      }
      else {
      global.Promise = factory();
      }
      }(function () {
       
      /**
      * Promise对象的内部状态
      *
      * @type {Object}
      */
      var Status = {
      PENDING: 'pending',
      FULLFILLED: 'resolved',
      REJECTED: 'rejected'
      };
       
      function empty() {}
       
      /**
      * Promise构造函数
      *
      * @constructor
      * @param {Function} resolver 此Promise对象管理的任务
      */
      function Promise(resolver) {
      // ES6原生的Promise构造函数中,若不通过`new`调用Promise的构造函数,会抛出TypeError异常。此处与其一致
      if (!(this instanceof Promise)) {
      throw new TypeError('TypeError: undefined is not a promise');
      }
       
      // ES6原生的Promise构造函数中,若无作为函数的resolver参数,会抛出TypeError异常。此处与其一致
      if (typeof resolver !== 'function') {
      throw new TypeError('TypeError: Promise resolver undefined is not a function');
      }
       
      /**
      * Promise对象内部的状态,初始为`pending`。状态只能由`pending`到`fullfilled`或`rejected`
      *
      * @type {string}
      */
      this._status = Status.PENDING;
       
      /**
      * Promise对象resolved/rejected后拥有的data/reason
      *
      * - 此处保存此值是为了当一个Promise对象被resolved或rejected后,继续对其调用`then`添加任务,后续处理仍能获得当前Promise的值
      *
      * @type {Mixed}
      */
      this._value;
       
      /**
      * 当前Promise被resolved/rejected后,需处理的任务
      *
      * - 由于同一个Promise对象可以调用多次`then`方法,以添加多个并行任务,所以此处是一个数组
      *
      * @type {Array.<Function>}
      */
      this._doneCallbacks = [];
      this._failCallbacks = [];
       
      var promise = this;
      resolver(
      function (data) {
      resolve(promise, data);
      },
      function (reason) {
      reject(promise, reason);
      }
      );
      }
       
      Promise.prototype = {
       
      constructor: Promise,
       
      /**
      * Promise的`then`方法
      *
      * @param {Function|Mixed} onResolve 当前Promise对象被resolved后,需处理的任务
      * @param {Function|Mixed} onReject 当前Promise对象被rejected后,需处理的任务
      * @return {Promise} 返回一个新的Promise对象,用于链式操作
      */
      then: function (onResolve, onReject) {
      var promise = new Promise(empty);
       
      this._doneCallbacks.push(makeCallback(promise, onResolve, 'resolve'));
      this._failCallbacks.push(makeCallback(promise, onReject, 'reject'));
       
      // 如果在一个已经被fullfilled或rejected的promise上调用then,则需要直接执行通过then注册的回调函数
      run(this);
       
      return promise;
      },
       
      /**
      * Promise的`done`方法
      *
      * @param {Function|Mixed} onResolve 当前Promise对象被resolved后,需处理的任务
      * @return {Promise} 返回一个新的Promise对象,用于链式操作
      */
      done: function (onResolve) {
      return this.then(onResolve, null);
      },
       
      /**
      * Promise的`fail`方法
      *
      * @param {Function|Mixed} onReject 当前Promise对象被rejected后,需处理的任务
      * @return {Promise} 返回一个新的Promise对象,用于链式操作
      */
      fail: function (onReject) {
      return this.then(null, onReject);
      },
       
      /**
      * Promise的`catch`方法
      *
      * @param {Function|Mixed} onFail 当前Promise对象被rejected后,需处理的任务
      * @return {Promise} 返回一个新的Promise对象,用于链式操作
      */
      catch: function (onFail) {
      return this.then(null, onFail);
      }
      };
       
      /**
      * 创建一个Promise对象,并用给定值resolve它
      *
      * @param {Mixed} value 用于resolve新创建的Promise对象的值
      * @return {Promise} 返回一个新的Promise对象,用于链式操作
      */
      Promise.resolve = function (value) {
      var promise = new Promise(empty);
      resolve(promise, value);
      return promise;
      };
       
      /**
      * 创建一个Promise对象,并用给定值reject它
      *
      * @param {Mixed} reason 用于reject新创建的Promise对象的值
      * @return {Promise} 返回一个新的Promise对象,用于链式操作
      */
      Promise.reject = function (reason) {
      var promise = new Promise(empty);
      reject(promise, reason);
      return promise;
      };
       
      /**
      * 返回一个promise,这个promise在iterable中的任意一个promise被解决或拒绝后,
      * 立刻以相同的解决值被解决或以相同的拒绝原因被拒绝
      *
      * @param {Iterable.<Promise|Mixed>} iterable 一组Promise对象或其它值
      * @return {Promise} 返回一个新的Promise对象,用于链式操作
      */
      Promise.race = function (iterable) {
      if (!iterable || !iterable.hasOwnProperty('length')) {
      throw new TypeError('TypeError: Parameter `iterable` must be a iterable object');
      }
       
      var promise = new Promise(empty);
      for (var i = 0, len = iterable.length; i < len; i++) {
      var iterate = iterable[i];
      if (!(iterate instanceof Promise)) {
      iterate = Promise.resolve(iterate);
      }
       
      iterate.then(resolveRaceCallback, rejectRaceCallback);
      }
       
      var settled = false;
       
      function resolveRaceCallback(data) {
      if (settled) {
      return;
      }
       
      settled = true;
      resolve(promise, data);
      }
       
      function rejectRaceCallback(reason) {
      if (settled) {
      return;
      }
       
      settled = true;
      reject(promise, reason);
      }
      };
       
      /**
      * 返回一个promise,该promise会在iterable参数内的所有promise都被解决后被解决
      *
      * @param {Iterable.<Promise|Mixed>} iterable 一组Promise对象或其它值
      * @return {Promise} 返回一个新的Promise对象,用于链式操作
      */
      Promise.all = function (iterable) {
      if (!iterable || !iterable.hasOwnProperty('length')) {
      throw new TypeError('TypeError: Parameter `iterable` must be a iterable object');
      }
       
      var promise = new Promise(empty);
      var length = iterable.length;
      for (var i = 0; i < length; i++) {
      var iterate = iterable[i];
      if (!(iterate instanceof Promise)) {
      iterate = Promise.resolve(iterate);
      }
       
      iterate.then(makeAllCallback(iterate, i, 'resolve'), makeAllCallback(iterate, i, 'reject'));
      }
       
      var result = [];
      var count = 0;
       
      function makeAllCallback(iterate, index, action) {
      return function (value) {
      if (action === 'reject') {
      reject(promise, value);
      return;
      }
       
      result[index] = value;
       
      if (++count === length) {
      resolve(promise, result);
      }
      }
      }
      };
       
      /**
      * 返回一个Deferred对象,包含一个新创建的Promise对象,以及`resolve`和`reject`方法
      *
      * @return {Deferred}
      */
      Promise.defer = function () {
      var promise = new Promise(empty);
       
      return {
      promise: promise,
      resolve: function (data) {
      resolve(promise, data);
      },
      reject: function (reason) {
      reject(promise, reason);
      }
      };
      };
       
      function run(promise) {
      // `then`方法中也会调用,所以此处仍需做一次判断
      if (promise._status === Status.PENDING) {
      return;
      }
       
      var value = promise._value;
      var callbacks = promise._status === Status.FULLFILLED
      ? promise._doneCallbacks
      : promise._failCallbacks;
       
      // Promise需要异步操作
      setTimeout(function () {
      for (var i = 0, len = callbacks.length; i < len; i++) {
      callbacks[i](value);
      }
      });
       
      // 每个promise只能被执行一次。虽然`_doneCallbacks`和`_failCallbacks`用户不应该直接访问,
      // 但还是可以访问到,保险起见,做清空处理。
      promise._doneCallbacks = [];
      promise._failCallbacks = [];
      }
       
      function resolve(promise, data) {
      if (promise._status !== Status.PENDING) {
      return;
      }
       
      promise._status = Status.FULLFILLED;
      promise._value = data;
       
      run(promise);
      }
       
      function reject(promise, reason) {
      if (promise._status !== Status.PENDING) {
      return;
      }
       
      promise._status = Status.REJECTED;
      promise._value = reason;
       
      run(promise);
      }
       
      function makeCallback(promise, callback, action) {
      return function promiseCallback(value) {
      // 如果传递了callback,则使用前一个promise传递过来的值作为参数调用callback,
      // 并根据callback的调用结果来处理当前promise
      if (typeof callback === 'function') {
      var x;
      try {
      x = callback(value);
      }
      catch (e) {
      // 如果调用callback时抛出异常,则直接用此异常对象reject当前promise
      reject(promise, e);
      }
       
      // 如果callback的返回值是当前promise,为避免造成死循环,需要抛出异常
      // 根据Promise+规范,此处应抛出TypeError异常
      if (x === promise) {
      var reason = new TypeError('TypeError: The return value could not be same with the promise');
      reject(promise, reason);
      }
      // 如果返回值是一个Promise对象,则当返回的Promise对象被resolve/reject后,再resolve/reject当前Promise
      else if (x instanceof Promise) {
      x.then(
      function (data) {
      resolve(promise, data);
      },
      function (reason) {
      reject(promise, reason);
      }
      );
      }
      else {
      var then;
      (function resolveThenable(x) {
      // 如果返回的是一个Thenable对象(此处逻辑有点坑,参照Promise+的规范实现)
      if (x && (typeof x === 'object'|| typeof x === 'function')) {
      try {
      then = x.then;
      }
      catch (e) {
      reject(promise, e);
      return;
      }
       
      if (typeof then === 'function') {
      // 调用Thenable对象的`then`方法时,传递进去的`resolvePromise`和`rejectPromise`方法(及下面的两个匿名方法)
      // 可能会被重复调用。但Promise+规范规定这两个方法有且只能有其中的一个被调用一次,多次调用将被忽略。
      // 此处通过`invoked`来处理重复调用
      var invoked = false;
      try {
      then.call(
      x,
      function (y) {
      if (invoked) {
      return;
      }
      invoked = true;
       
      // 避免死循环
      if (y === x) {
      throw new TypeError('TypeError: The return value could not be same with the previous thenable object');
      }
       
      // y仍有可能是thenable对象,递归调用
      resolveThenable(y);
      },
      function (e) {
      if (invoked) {
      return;
      }
      invoked = true;
       
      reject(promise, e);
      }
      );
      }
      catch (e) {
      // 如果`resolvePromise`和`rejectPromise`方法被调用后,再抛出异常,则忽略异常
      // 否则用异常对象reject此Promise对象
      if (!invoked) {
      reject(promise, e);
      }
      }
      }
      else {
      resolve(promise, x);
      }
      }
      else {
      resolve(promise, x);
      }
      }(x));
      }
      }
      // 如果未传递callback,直接用前一个promise传递过来的值resolve/reject当前Promise对象
      else {
      action === 'resolve'
      ? resolve(promise, value)
      : reject(promise, value);
      }
      };
      }
       
      return Promise;
      }, this));
  • 相关阅读:
    WebRTC之完整搭建Jitsi Meet指南
    使用Jibri进行Jitsi Meet视频录制
    完整开源免费视频会议Jitsi-meet安装教程
    iOS聊天起泡(背景图片被拉伸不变形)----转载--待验证
    技术人对赚钱的思考与摸索
    模板引擎的思考
    SpringBoot单文件与多文件上传
    数据库被删之反思
    分布式配置中心之思考
    正版office产品密钥-激活码
  • 原文地址:https://www.cnblogs.com/oxspirt/p/13096764.html
Copyright © 2011-2022 走看看