zoukankan      html  css  js  c++  java
  • 【原创】when.js2.7.1源码解析

    现在,用回调处理一些复杂的逻辑,显得代码臃肿,难于阅读,特别是异步,嵌套。

    解决这样的问题,可以是之前所说的Backbone.Events的pubsub,或者是今天要说的when.js所实现的promise。

    在前端,jQuery的ajax全面改写就是为了引入promise这一套,为了使代码更流畅,更易于维护,事实上更容易实现复杂的需求。

    jQuery Deferred所实现的promise并不是那么的规范,功能也并不能么全,在前端可以很方便的使用就是了,那么在后端(nodejs),我推荐

    使用when.js,它的接口清晰,功能强大,架构更是很精妙,并且它在实现了完整的Promise A+后,又添加了好多扩展功能,使得在实际应用中,

    能够很方便的写出优秀的代码。

    所以对于这样强大的代码,当然是要去读一遍,学学作者的架构思路,花了几天时间阅读,对源代码进行了中文注释讲解(其中有放一些例子),

    就贴在下面了,可能会有点长(看源代码都需要耐心嘛),如果有错误还望指证出来,多谢啦~

       1 /** @license MIT License (c) copyright 2011-2013 original author or authors */
       2 
       3 /**
       4  * A lightweight CommonJS Promises/A and when() implementation
       5  * when is part of the cujo.js family of libraries (http://cujojs.com/)
       6  *
       7  * Licensed under the MIT License at:
       8  * http://www.opensource.org/licenses/mit-license.php
       9  *
      10  * @author Brian Cavalier
      11  * @author John Hann
      12  * @version 2.7.1
      13  */
      14  // 首先是规范的兼容AMD(比如requirejs)和CMD(比如nodejs)
      15 (function(define) { 'use strict';
      16 define(function (require) {
      17 
      18     // Public API
      19     // 接口很明确就是以下这些
      20     // 首先promise对象拥有的三个状态:pending, resolved(fulfilled), rejected
      21     // 再然后需要理解promise对象和defer对象的关系
      22     // 可以简单的理解为:defer对象内置了一个promise对象
      23     // 它拥有两个接口resolve和reject来控制promise对象的最终的状态,从而进行异步操作的处理
      24     when.promise   = promise;    // Create a pending promise(创建一个状态还是pending的promise对象)
      25     when.resolve   = resolve;    // Create a resolved promise (创建一个状态已经是resolved的promise对象)
      26     when.reject    = reject;     // Create a rejected promise(创建一个状态已经是resolved的promise对象)
      27     when.defer     = defer;      // Create a {promise, resolver} pair(创建一个defer对象)
      28 
      29     when.join      = join;       // Join 2 or more promises(解决多个promiseOrValue对象,与all想死)
      30 
      31     when.all       = all;        // Resolve a list of promises(等待所有promise都resolve,新的promise才resolve)
      32     when.map       = map;        // Array.map() for promises (类似数组的map)
      33     when.reduce    = reduce;     // Array.reduce() for promises(类似数组的reduce)
      34     when.settle    = settle;     // Settle a list of promises(处理promiseOrValue数组,返回state数组)
      35 
      36     when.any       = any;        // One-winner race(一个promiseOrValue resolve,新的promiseresolve)
      37     when.some      = some;       // Multi-winner race(some个promiseOrValue resolve,新的promiseresolve)
      38 
      39     when.isPromise = isPromiseLike;  // DEPRECATED: use isPromiseLike
      40     when.isPromiseLike = isPromiseLike; // Is something promise-like, aka thenable 
      41 
      42     /**
      43      * Register an observer for a promise or immediate value.
      44      *
      45      * @param {*} promiseOrValue
      46      * @param {function?} [onFulfilled] callback to be called when promiseOrValue is
      47      *   successfully fulfilled.  If promiseOrValue is an immediate value, callback
      48      *   will be invoked immediately.
      49      * @param {function?} [onRejected] callback to be called when promiseOrValue is
      50      *   rejected.
      51      * @param {function?} [onProgress] callback to be called when progress updates
      52      *   are issued for promiseOrValue.
      53      * @returns {Promise} a new {@link Promise} that will complete with the return
      54      *   value of callback or errback or the completion value of promiseOrValue if
      55      *   callback and/or errback is not supplied.
      56      */
      57 
      58     // 官方的解释是:为一个promise对象或者立即数注册一个观察者
      59     // 其实简单点就是
      60     // 当promiseOrValue为resolved状态时,onRejected回调被调用
      61     // 1. 当promiseOrValue被resolve时,onFulfilled回调被调用
      62     // 2. 当promise为reject状态时,onRejected回调被调用
      63     // 3. 当promise为notify状态时,onProgress回调被调用
      64     // 注意:
      65     // 上述的第一点用的promiseOrValue,这里的value指的是立即数,立即数使得生成promise对象开始就是resolved状态
      66     // 另外这里的promiseOrValue也可以是一个数组(即[promiseOrValue1, promiseOrValue2, ...])
      67     function when(promiseOrValue, onFulfilled, onRejected, onProgress) {
      68         // Get a trusted promise for the input promiseOrValue, and then
      69         // register promise handlers
      70         // 首先这里先对promiseOrValue进行转换(cast方法),将其转变为promise对象
      71         // 然后调用promise对象的then方法,并将用户提供的参数传递给then方法,等待被调用
      72         // 最后返回then方法创建的新的promise对象,这样来维持链式
      73         // 而且onFulfilled一般是函数,返回的值将作为形参传递给下一个onFulfilled,
      74         // 但如果不是函数那么onFulfilled的理应接受的参数将继续传递给下一个onFulfilled,
      75         // 也就是说可以继续这样调用:
      76         // when('hello', 'notFunction').then(function (v) {
      77         //     console.log(v);// 这里的v就是hello
      78         // });
      79         return cast(promiseOrValue).then(onFulfilled, onRejected, onProgress);
      80     }
      81 
      82     /**
      83      * Creates a new promise whose fate is determined by resolver.
      84      * @param {function} resolver function(resolve, reject, notify)
      85      * @returns {Promise} promise whose fate is determine by resolver
      86      */
      87      // 创建一个promise对象,它的最终状态又resolver函数决定,为什么?
      88      // 因为resovler函数作为用户自定义函数会被传递三个形参,就是promise对象的三个内置改变状态的接口
      89      // when.promise(function (reslove, reject, notify) {
      90      //    resolve('xxx'); // fn1 被调用
      91      //    //reject('xxx');  // fn2 被调用
      92      //    //notify('xxx');  // fn3 被调用
      93 
      94      // }).then(fn1, fn2, fn3);
      95     function promise(resolver) {
      96         // 实质是调用Promise构造函数
      97         // 这里的PromiseStatus不是很清楚,好像是when/monitor下的文件,应该是辅助文件吧,
      98         // 可以先不用管
      99         return new Promise(resolver,
     100             monitorApi.PromiseStatus && monitorApi.PromiseStatus());
     101     }
     102 
     103     /**
     104      * Trusted Promise constructor.  A Promise created from this constructor is
     105      * a trusted when.js promise.  Any other duck-typed promise is considered
     106      * untrusted.
     107      * @constructor
     108      * @returns {Promise} promise whose fate is determine by resolver
     109      * @name Promise
     110      */
     111      // Promise构造器
     112      // resolver上面已经说过,是一个函数
     113      // status暂时先不管,跟程序主体关系不大
     114     function Promise(resolver, status) {
     115         var self, value, consumers = [];
     116 
     117         self = this;
     118         this._status = status;
     119         this.inspect = inspect;
     120         this._when = _when;
     121 
     122         // Call the provider resolver to seal the promise's fate
     123         // 调用使用者提供的resolver函数,并将操作该promise对象“命运”的三个接口函数传递给resolver函数
     124         // 利用try catch 捕获异常,毕竟resolver函数是使用者自定义的
     125         // 如果异常将该promise对象reject
     126         // 其实这里是有些疑问的?如果该异常出现在promise对象resolve或者reject之后,
     127         // 这里catch里的reject就毫无用处了(毕竟promise的最终状态是不可以改变的)
     128         try {
     129             resolver(promiseResolve, promiseReject, promiseNotify);
     130         } catch(e) {
     131             promiseReject(e);
     132         }
     133 
     134         /**
     135          * Returns a snapshot of this promise's current status at the instant of call
     136          * @returns {{state:String}}
     137          */
     138          // inspect函数用来查看当前promise对象的状态以及相关的值
     139         function inspect() {
     140             //这里的value有三种情况:
     141             // pending时,为undefined
     142             // resolved时,是FulfilledPromise的实例
     143             // rejected时,是FulfilledPromise的实例
     144             // 所以在非空时这才有了对应的inspect方法
     145             return value ? value.inspect() : toPendingState();
     146         }
     147 
     148         /**
     149          * Private message delivery. Queues and delivers messages to
     150          * the promise's ultimate fulfillment value or rejection reason.
     151          * @private
     152          */
     153          // 这里的_when私有函数起到至关重要的作用。
     154          // 这里它利用consumers和enqueue数组存储经过封装后的callback,不同的是:
     155          // consumers里的callback是等待该promise对象resolve或者reject后执行
     156          // enqueue里的callback是等待下个tick执行,或者说是延时执行(此时该promise对象已经resolved或者rejected了)
     157          // 另外巧妙通过闭包实现了对onFulfilled,onRejected,onProgress的访问,
     158          // 而无需像jQuery Deferrred那样通过创建维护三个队列存储callback
     159         function _when(resolve, notify, onFulfilled, onRejected, onProgress) {
     160             // 通过consumers参数判断该promise对象是否已经有了最终状态(即resolved或者rejected)
     161             // resloved(rejected)了,加入队列在下一个时间周期等待执行
     162             // pending状态,存储起来在,等待适当的时候被执行(reslove或者reject的时候)
     163             consumers ? consumers.push(deliver) : enqueue(function() { deliver(value); });
     164 
     165             function deliver(p) {
     166                 // 这里的p依然有三种值
     167                 // 1. 处于pending状态的promise对象
     168                 //    这种情苦发生在onFulfilled返回一个处于pending状态的promie对象,
     169                 //   利用p._when关联之后的promise对象从而继续完成同步操作
     170                 // 如:(虽然异步,但是却是同步的写法,免去了callback的嵌套)
     171                 // when.promise(function () {
     172                 //     var defer = when.defer();
     173                 //     setTimout(function () {
     174                 //         defer.resolve('xx');
     175                 //     }, 50)
     176                 // }).then(function (val) {
     177                 //         console.log(val); // xx
     178                 // });
     179                 // 2. FulfilledPromise对象
     180                 // 3. RejectedPromise对象
     181                 // 所以这里的p._when调用的方法出处各有不同
     182                 p._when(resolve, notify, onFulfilled, onRejected, onProgress);
     183             }
     184         }
     185 
     186         /**
     187          * Transition from pre-resolution state to post-resolution state, notifying
     188          * all listeners of the ultimate fulfillment or rejection
     189          * @param {*} val resolution value
     190          */
     191         // 当前promise对象的resolve接口
     192         function promiseResolve(val) {
     193             // val的值可以是有四种值
     194             // 1. 立即数(经过coerce处理最终变为FulfilledPromise对象)
     195             // 2. promise对象
     196             // 3. RejectedPromise对象(仅供内部传递,因为RejectedPromise是未暴露的函数类)
     197             // 3. FulfilledPromise对象(仅供内部传递)
     198             // 同样给出一个例子:
     199             // when.promise(function (resolve) {
     200 
     201             //     // resolve('hello'); // 情况一立即数
     202 
     203             //     var defer = when.defer();
     204 
     205             //     setTimeout(function () { // 情况二promise对象,同样可以将setTimeout去掉试试
     206             //         defer.resolve('hello');
     207             //         // defer.reject('hello');
     208             //     }, 200);
     209 
     210             //     resolve(defer.promise);
     211             // }).then(function (value) {
     212             //      console.log(value); // hello
     213             // });
     214 
     215             // consumers用来判断promise对象是否有了最终状态(即pending->resolved/rejected)
     216             // 因为根据Promises/A+规范规定,prmoise对象的最终状态是不可变的
     217             // 也就是说resolve和reject只会被执行一次
     218             if(!consumers) {
     219                 return;
     220             }
     221 
     222             // 将consumers置为undefined表示promise对象已经resolve或者reject了
     223             var queue = consumers;
     224             consumers = undef;
     225 
     226             // 将当前要执行的任务入队列,等待下一个时刻执行,将异步进行到底
     227             enqueue(function () {
     228                 // coerce进行val的转换
     229                 // 转换为promise对象或者promise的子类RejectedPromise/FulfilledPromise的实例
     230                 // 传递给value,value很重要,作为最终的值,之后回通过必包传递给一个关联回调
     231                 value = coerce(self, val);
     232                 if(status) {
     233                     updateStatus(value, status);
     234                 }
     235                 // 运行consumers里传递过来的函数队列
     236                 runHandlers(queue, value);
     237             });
     238         }
     239 
     240         /**
     241          * Reject this promise with the supplied reason, which will be used verbatim.
     242          * @param {*} reason reason for the rejection
     243          */
     244          // 当前promise对象的reject接口
     245          // 实质还是利用resolve的接口,只不过是主动传递RejectedPromise的实例
     246         function promiseReject(reason) {
     247             promiseResolve(new RejectedPromise(reason));
     248         }
     249 
     250         /**
     251          * Issue a progress event, notifying all progress listeners
     252          * @param {*} update progress event payload to pass to all listeners
     253          */
     254          // notify就是一个进度提示,这在做一些进度方面的组件是很有用户体验的,比如flash uploader
     255          // 显然既然是进度,那么首先promise对象是必须还处于pending状态,notify才会有效
     256          // 所以consumers必须不为空
     257          // 给个例子:
     258         // when.promise(function (resolve, reject, notify) {
     259 
     260         //     var counter = 0;
     261         //     var timer = setInterval(function () {
     262         //         counter++;
     263         //         notify(counter);
     264 
     265         //         if (counter === 10) {
     266         //             resolve('over');
     267         //             clearInterval(timer);
     268         //         }
     269         //     }, 1);
     270         // }).then(function (value) {
     271         //     console.log(value);
     272         // }, undefined, function (update) {
     273         //     console.log(update);
     274         // });
     275         // 结果是 1 2 3 4 5 6 7 8 9 10 over
     276         function promiseNotify(update) {
     277             if(consumers) {
     278                 var queue = consumers;
     279                 enqueue(function () {
     280                     runHandlers(queue, new ProgressingPromise(update));
     281                 });
     282             }
     283         }
     284     }
     285 
     286     // 接下来是Promise的原型方法,最重要的就是then方法
     287     promisePrototype = Promise.prototype;
     288 
     289     /**
     290      * Register handlers for this promise.
     291      * @param [onFulfilled] {Function} fulfillment handler
     292      * @param [onRejected] {Function} rejection handler
     293      * @param [onProgress] {Function} progress handler
     294      * @return {Promise} new Promise
     295      */
     296      // then方法是Promises/A+的核心,也是链式的关键,用来注册三种回调
     297      // 通过调用_when的私有方法能做到以下几点:
     298      // 1. 进行callback的注册
     299      // 2. 创建新的promise对象(newPromise)并返回,继续链式下去
     300      // 3. 将newPromise对象的决定权(即三个内置接口)交付给调用then方法的promise对象(即与之关联在一起)
     301     promisePrototype.then = function(onFulfilled, onRejected, onProgress) {
     302         var self = this;
     303 
     304         return new Promise(function(resolve, reject, notify) {
     305             self._when(resolve, notify, onFulfilled, onRejected, onProgress);
     306         }, this._status && this._status.observed());
     307     };
     308 
     309     /**
     310      * Register a rejection handler.  Shortcut for .then(undefined, onRejected)
     311      * @param {function?} onRejected
     312      * @return {Promise}
     313      */
     314      // 很明显内部调用了then方法,只传递了onRejected函数
     315      // 其实相当于promise.then(undef, onRejected)的快捷键
     316     promisePrototype['catch'] = promisePrototype.otherwise = function(onRejected) {
     317         return this.then(undef, onRejected);
     318     };
     319 
     320     /**
     321      * Ensures that onFulfilledOrRejected will be called regardless of whether
     322      * this promise is fulfilled or rejected.  onFulfilledOrRejected WILL NOT
     323      * receive the promises' value or reason.  Any returned value will be disregarded.
     324      * onFulfilledOrRejected may throw or return a rejected promise to signal
     325      * an additional error.
     326      * @param {function} onFulfilledOrRejected handler to be called regardless of
     327      *  fulfillment or rejection
     328      * @returns {Promise}
     329      */
     330      // finally和ensure方法保证promise对象无论什么状态的情况下,最终都会执行onFulfilledOrRejected
     331      // 但是onFulfilledOrRejected是不带任何参数的
     332      // 另外,finally(ensure)方法如果后面继续链式,添加then方法,最终执行是与该promise对象相关的,并且接受
     333      // promise对象的resolve的value值和reject的reason值(与finally的返回值无关,除非onFulfilledOrRejected
     334      // 回调报出异常或者返回rejected的promise对象)
     335      // 举个例子:
     336     // var when = require('when');
     337     // var defer = when.defer();
     338 
     339     // defer.promise.finally(function () {
     340     //     console.log(arguments);     // {}
     341 
     342     //     var defer2 = when.defer();
     343     //     defer2.reject('xxx');
     344 
     345     //     return defer2.promise;
     346     // }).then(function (value) {
     347     //     console.log('value: ' + value);
     348     // }, function (reason) {
     349     //     console.log('reason: ' + reason); // reason: xxx
     350     // });
     351     // defer.resolve('hello');
     352     promisePrototype['finally'] = promisePrototype.ensure = function(onFulfilledOrRejected) {
     353         // 这里利用yield(this),试图将接下来的newPromise对象的控制权交给当前的promise对象
     354         return typeof onFulfilledOrRejected === 'function'
     355             ? this.then(injectHandler, injectHandler)['yield'](this)
     356             : this;
     357 
     358         function injectHandler() {
     359             // 这里是为了配合yield方法,试图想返回一个resolved的promise对象
     360             // 但是onFulfilledOrRejected(),如果发生异常,或者返回rejectedpromise对象
     361             // 将会使得结果与当前promise对象的状态无关了,就像上面代码没有输出hello一样
     362             return resolve(onFulfilledOrRejected());
     363         }
     364     };
     365 
     366     /**
     367      * Terminate a promise chain by handling the ultimate fulfillment value or
     368      * rejection reason, and assuming responsibility for all errors.  if an
     369      * error propagates out of handleResult or handleFatalError, it will be
     370      * rethrown to the host, resulting in a loud stack track on most platforms
     371      * and a crash on some.
     372      * @param {function?} handleResult
     373      * @param {function?} handleError
     374      * @returns {undefined}
     375      */
     376      // done方法有两个作用:
     377      // 1. 结束链式
     378      // 2. 异常处理
     379      // 如下:
     380     // var when = require('when');
     381     // var defer = when.defer();
     382 
     383     // defer.promise.done(function () {
     384     //     console.log(arguments)
     385     // }, function (value) {
     386     //     var defer = when.defer();
     387     //     defer.reject(value)
     388     //     return defer.promise();
     389     // });
     390     // defer.reject('world');
     391     // 将会报出程序异常,结束程序执行
     392     promisePrototype.done = function(handleResult, handleError) {
     393         this.then(handleResult, handleError)['catch'](crash);
     394     };
     395 
     396     /**
     397      * Shortcut for .then(function() { return value; })
     398      * @param  {*} value
     399      * @return {Promise} a promise that:
     400      *  - is fulfilled if value is not a promise, or
     401      *  - if value is a promise, will fulfill with its value, or reject
     402      *    with its reason.
     403      */
     404      // 该方法传递了value参数(用于闭包访问),内部调用了then方法,只传递了onFulfilled回调
     405      // value值可以是立即数也是是promise对象
     406      // 当调用yield方法的originalPromise被rejected,返回的newPromise对象也会因为同样的reason被rejected
     407      // 而当originalPromise被resolved时,要分为两种情况:
     408      // 1. 当value为立即数,那么newPromise对象将被resolved,且被传递value值
     409      // 2. 当value为promise对象,那么返回的newPromise的命运(最后状态)将由value的状态决定,且被传递promise对象
     410      // resolved的value值,或者rejected的reason值
     411      // 总结,清楚then方法就可以很容易看清,yield内部通过只传递了onFulfilled回调,这个是关键因素
     412      // 来个例子:
     413     // var defer = when.defer();
     414     // var defer2 = when.defer();
     415 
     416     // defer.promise.yield(defer2.promise).then(function (value) {
     417     //     console.log('value: ' + value);
     418     // }, function (reason) {
     419     //     console.log('reason: ' + reason);
     420     // });
     421 
     422     // defer.reject('hello');
     423     // // defer.resolve('hello');
     424 
     425     // defer2.resolve('world');
     426     // // defer2.reject('world');
     427 
     428     // 结果:当defer->resolve&&defer2->resolve,输出value: world
     429     //      当defer->resolve&&defer2->rejected,输出reason: world
     430     //      当defer->rejected(跟defer2无关),输出reason: hello
     431 
     432     promisePrototype['yield'] = function(value) {
     433         return this.then(function() {
     434             return value;
     435         });
     436     };
     437 
     438     /**
     439      * Runs a side effect when this promise fulfills, without changing the
     440      * fulfillment value.
     441      * @param {function} onFulfilledSideEffect
     442      * @returns {Promise}
     443      */
     444      // 1. 当promise对象resolved时,onFulfilledSideEffect被执行,对于onFulfilledSideEffect的返回值
     445      // 没有任何意义,会被无视原因时因为['yield'](this)这句,迫使后面的promise对象与当前promise对象关联
     446      // 在一起,传入后面callback的值也是当前promise对象resovle的value,或者reject的reason,但是如果
     447      // onFulfilledSideEffect抛出异常或者返回rejected的promise对象,那么将会触发之后promise对象
     448      // 的onRejected回调,并传入异常信息
     449      // 2. 当promise对象rejected时,onFulfilledSideEffect不会被执行,之后的promise对象的onRejected回调
     450      // 会被触发,并被传入当前promise对象reject的reason
     451      // 例如:
     452     // var defer = when.defer();
     453 
     454     // defer.promise.tap(function (value) {
     455 
     456     //     return 'good';
     457     // }).then(function (value) {
     458     //     console.log('value: ' + value); // value: hello
     459     // }, function (reason) {
     460     //     console.log('reason: ' + reason);
     461     // });
     462     // defer.resolve('hello');
     463     // 总结:上述的输出并不会因为我return了good而改变接下来输出的value值
     464     promisePrototype.tap = function(onFulfilledSideEffect) {
     465         return this.then(onFulfilledSideEffect)['yield'](this);
     466     };
     467 
     468     /**
     469      * Assumes that this promise will fulfill with an array, and arranges
     470      * for the onFulfilled to be called with the array as its argument list
     471      * i.e. onFulfilled.apply(undefined, array).
     472      * @param {function} onFulfilled function to receive spread arguments
     473      * @return {Promise}
     474      */
     475     promisePrototype.spread = function(onFulfilled) {
     476         return this.then(function(array) {
     477             // array may contain promises, so resolve its contents.
     478             return all(array, function(array) {
     479                 return onFulfilled.apply(undef, array);
     480             });
     481         });
     482     };
     483 
     484     /**
     485      * Shortcut for .then(onFulfilledOrRejected, onFulfilledOrRejected)
     486      * @deprecated
     487      */
     488      // 即将被废弃,可用finally(ensure)代替
     489     promisePrototype.always = function(onFulfilledOrRejected, onProgress) {
     490         return this.then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress);
     491     };
     492 
     493     /**
     494      * Casts x to a trusted promise. If x is already a trusted promise, it is
     495      * returned, otherwise a new trusted Promise which follows x is returned.
     496      * @param {*} x
     497      * @returns {Promise}
     498      */
     499     function cast(x) {
     500         return x instanceof Promise ? x : resolve(x);
     501     }
     502 
     503     /**
     504      * Returns a resolved promise. The returned promise will be
     505      *  - fulfilled with promiseOrValue if it is a value, or
     506      *  - if promiseOrValue is a promise
     507      *    - fulfilled with promiseOrValue's value after it is fulfilled
     508      *    - rejected with promiseOrValue's reason after it is rejected
     509      * In contract to cast(x), this always creates a new Promise
     510      * @param  {*} value
     511      * @return {Promise}
     512      */
     513      // 内部调用when.promise方法,创建一个状态为resolved的promise对象
     514      // 值得注意的是这里的value可以是一个promise对象
     515      // 像这样:
     516      // var defer = when.defer();
     517      // when.resolve(defer.promise).then(function (val) {
     518      //     console.log(val); // hello
     519      // });
     520      // defer.resolve('hello');
     521     function resolve(value) {
     522         return promise(function(resolve) {
     523             resolve(value);
     524         });
     525     }
     526 
     527     /**
     528      * Returns a rejected promise for the supplied promiseOrValue.  The returned
     529      * promise will be rejected with:
     530      * - promiseOrValue, if it is a value, or
     531      * - if promiseOrValue is a promise
     532      *   - promiseOrValue's value after it is fulfilled
     533      *   - promiseOrValue's reason after it is rejected
     534      * @param {*} promiseOrValue the rejected value of the returned {@link Promise}
     535      * @return {Promise} rejected {@link Promise}
     536      */
     537      // 看到这里,可能会疑惑为什么代码是这样的?而不是这样的:
     538      // function reject(promiseOrValue) {
     539      //     return promise(function(resolve, reject) {
     540      //         reject(value);
     541      //     });
     542      // }
     543      // 问题在与reject方法只能接受字符串reason,然后构造成RejectedPromise实例,
     544      // 不想resolve方法那样能够接受promise对象
     545      // 为了满足同样能将promise对象作为参数,利用when内部处理promiseOrValue
     546      // 例如:
     547      // var defer = when.defer();
     548 
     549      // when.reject(defer.promise).then(function (value) {
     550      //     console.log('value: ' + value);
     551      // }, function (reason) {
     552      //     console.log('reason: ' + reason); // reason: bad/good
     553      // });
     554 
     555      // // defer.reject('bad');
     556      // defer.resolve('good');
     557      // 无论你的promise最终resolve还是reject,最终都是执行onRejected回调。
     558      // 这里有个巧妙的地方就是
     559      // 当resolve的时候,会利用下面的new RejectedPromise(e)来生成RejectedPromise对象
     560      // 传递给下promise对象的resolve接口,进而执行onRejected
     561      // 当reject时,会自动生成RejectedPromise对象,下面的new RejectedPromise(e)并不会被调用
     562     function reject(promiseOrValue) {
     563         return when(promiseOrValue, function(e) {
     564             return new RejectedPromise(e);
     565         });
     566     }
     567 
     568     /**
     569      * Creates a {promise, resolver} pair, either or both of which
     570      * may be given out safely to consumers.
     571      * The resolver has resolve, reject, and progress.  The promise
     572      * has then plus extended promise API.
     573      *
     574      * @return {{
     575      * promise: Promise,
     576      * resolve: function:Promise,
     577      * reject: function:Promise,
     578      * notify: function:Promise
     579      * resolver: {
     580      *    resolve: function:Promise,
     581      *    reject: function:Promise,
     582      *    notify: function:Promise
     583      * }}}
     584      */
     585      // defer函数用来返回一个deferred对象
     586      // 内部包含promise对象以及操纵promise对象状态的三个接口
     587      // 所以说deferred对象会改变promise的状态,而promise(defer.promise)对象时不可以改变自身的状态,
     588      // 这就相当于jQuery Deferred中所谓的“受限制的deferred对象”
     589     function defer() {
     590         // deferred表示即将返回给用户的deferred对象
     591         // pending可以理解为deferred.promise的别名,简单高效
     592         // resolved表示该deferred是否已经reject或者resolve了
     593         var deferred, pending, resolved;
     594 
     595         // Optimize object shape
     596         // 包装一下
     597         deferred = {
     598             promise: undef, resolve: undef, reject: undef, notify: undef,
     599             resolver: { resolve: undef, reject: undef, notify: undef }
     600         };
     601 
     602         // 创建promise对象,将控制权交给makeDeferred函数
     603         deferred.promise = pending = promise(makeDeferred);
     604 
     605         return deferred;
     606 
     607         // 给deferred对象添加三个控制promise对象的接口
     608         function makeDeferred(resolvePending, rejectPending, notifyPending) {
     609             deferred.resolve = deferred.resolver.resolve = function(value) {
     610                 // 对于已经resolved的情况
     611                 // 根据传递进来的value创建已经新的resolved的promise对象
     612                 // 可以说已经与当前的promise对象已经没关系了
     613                 if(resolved) {
     614                     return resolve(value);
     615                 }
     616                 resolved = true;
     617                 // 执行promise对象的resolve
     618                 resolvePending(value);
     619                 // 返回resolved的promise对象,保持链式,被传递的值resolve时的只
     620                 return pending;
     621             };
     622 
     623             // reject同上
     624             deferred.reject  = deferred.resolver.reject  = function(reason) {
     625                 if(resolved) {
     626                     return resolve(new RejectedPromise(reason));
     627                 }
     628                 resolved = true;
     629                 rejectPending(reason);
     630                 return pending;
     631             };
     632 
     633             deferred.notify  = deferred.resolver.notify  = function(update) {
     634                 notifyPending(update);
     635                 return update;
     636             };
     637         }
     638     }
     639 
     640     /**
     641      * Run a queue of functions as quickly as possible, passing
     642      * value to each.
     643      */
     644      // 简单的遍历队列,执行函数
     645     function runHandlers(queue, value) {
     646         for (var i = 0; i < queue.length; i++) {
     647             queue[i](value);
     648         }
     649     }
     650 
     651     /**
     652      * Coerces x to a trusted Promise
     653      * @param {*} x thing to coerce
     654      * @returns {*} Guaranteed to return a trusted Promise.  If x
     655      *   is trusted, returns x, otherwise, returns a new, trusted, already-resolved
     656      *   Promise whose resolution value is:
     657      *   * the resolution value of x if it's a foreign promise, or
     658      *   * x if it's a value
     659      */
     660      // 将x转换为对应的可信任的promise对象
     661     function coerce(self, x) {
     662         if (x === self) {
     663             return new RejectedPromise(new TypeError());
     664         }
     665 
     666         // 已经是promise对象,直接返回
     667         // 比如:promise的对象或者它的三个子类实例
     668         if (x instanceof Promise) {
     669             return x;
     670         }
     671 
     672         try {
     673             var untrustedThen = x === Object(x) && x.then;
     674 
     675             return typeof untrustedThen === 'function'
     676                 ? assimilate(untrustedThen, x)
     677                 : new FulfilledPromise(x);
     678         } catch(e) {
     679             return new RejectedPromise(e);
     680         }
     681     }
     682 
     683     /**
     684      * Safely assimilates a foreign thenable by wrapping it in a trusted promise
     685      * @param {function} untrustedThen x's then() method
     686      * @param {object|function} x thenable
     687      * @returns {Promise}
     688      */
     689      // 将x为obj且带有then的函数进行封装并传递resolve和reject接口
     690      // 返回promise对象
     691     function assimilate(untrustedThen, x) {
     692         return promise(function (resolve, reject) {
     693             fcall(untrustedThen, x, resolve, reject);
     694         });
     695     }
     696 
     697     // 对Promise的原型继承(原生方法优先)
     698     makePromisePrototype = Object.create ||
     699         function(o) {
     700             function PromisePrototype() {}
     701             PromisePrototype.prototype = o;
     702             return new PromisePrototype();
     703         };
     704 
     705     /**
     706      * Creates a fulfilled, local promise as a proxy for a value
     707      * NOTE: must never be exposed
     708      * @private
     709      * @param {*} value fulfillment value
     710      * @returns {Promise}
     711      */
     712      // FulfilledPromise用于,当deferred.relove(value)时,对value的封装
     713     function FulfilledPromise(value) {
     714         this.value = value;
     715     }
     716 
     717     // 原型继承
     718     FulfilledPromise.prototype = makePromisePrototype(promisePrototype);
     719 
     720     // 返回promise的状态
     721     FulfilledPromise.prototype.inspect = function() {
     722         return toFulfilledState(this.value);
     723     };
     724 
     725     FulfilledPromise.prototype._when = function(resolve, _, onFulfilled) {
     726         // 这里的resolve适用于控制下一个关联的promise对象的
     727         // 并且onFulfilled会被传递reslove(value)中的value值
     728         // 如果onFulfilled有返回值,那么返回值会传递给下一个promise对象的回调函数
     729         // 另外onFulfilled也可以不是对象,那么将此时的value传递给下一个promise对象的回调函数
     730         // 对于用户自定义的函数onFulfilled采用try catch
     731         try {
     732             resolve(typeof onFulfilled === 'function' ? onFulfilled(this.value) : this.value);
     733         } catch(e) {
     734             resolve(new RejectedPromise(e));
     735         }
     736     };
     737 
     738     /**
     739      * Creates a rejected, local promise as a proxy for a value
     740      * NOTE: must never be exposed
     741      * @private
     742      * @param {*} reason rejection reason
     743      * @returns {Promise}
     744      */
     745      // RejectedPromise用于,当deferred.reject(value)时,对value的封装
     746     function RejectedPromise(reason) {
     747         this.value = reason;
     748     }
     749 
     750     RejectedPromise.prototype = makePromisePrototype(promisePrototype);
     751 
     752     RejectedPromise.prototype.inspect = function() {
     753         return toRejectedState(this.value);
     754     };
     755 
     756     RejectedPromise.prototype._when = function(resolve, _, __, onRejected) {
     757         // 这里值得注意的是在onRejected不存在时,会将this对象作为一下promise对象的回调函数
     758         // 保证RejectedPromise对象传递给下一个onRejected回调
     759         // 而且注意这里也是用的resolve函数,而不是想像中的reject,所以在进行then方法的
     760         // 链式调用下,如果一个promise对象resolved或rejected,它下一个promise对象会执行onFulfilled
     761         // 除非你当时返回的一个rejected对象
     762         try {
     763             resolve(typeof onRejected === 'function' ? onRejected(this.value) : this);
     764         } catch(e) {
     765             resolve(new RejectedPromise(e));
     766         }
     767     };
     768 
     769     /**
     770      * Create a progress promise with the supplied update.
     771      * @private
     772      * @param {*} value progress update value
     773      * @return {Promise} progress promise
     774      */
     775      // ProgressingPromise用于,当deferred.notify(value)时,对value的封装
     776     function ProgressingPromise(value) {
     777         this.value = value;
     778     }
     779 
     780     ProgressingPromise.prototype = makePromisePrototype(promisePrototype);
     781 
     782     ProgressingPromise.prototype._when = function(_, notify, f, r, u) {
     783         try {
     784             notify(typeof u === 'function' ? u(this.value) : this.value);
     785         } catch(e) {
     786             notify(e);
     787         }
     788     };
     789 
     790     /**
     791      * Update a PromiseStatus monitor object with the outcome
     792      * of the supplied value promise.
     793      * @param {Promise} value
     794      * @param {PromiseStatus} status
     795      */
     796     function updateStatus(value, status) {
     797         value.then(statusFulfilled, statusRejected);
     798 
     799         function statusFulfilled() { status.fulfilled(); }
     800         function statusRejected(r) { status.rejected(r); }
     801     }
     802 
     803     /**
     804      * Determines if x is promise-like, i.e. a thenable object
     805      * NOTE: Will return true for *any thenable object*, and isn't truly
     806      * safe, since it may attempt to access the `then` property of x (i.e.
     807      *  clever/malicious getters may do weird things)
     808      * @param {*} x anything
     809      * @returns {boolean} true if x is promise-like
     810      */
     811      // 判断一个对象是否like promise对象,很简单,即判断是否有then方法
     812     function isPromiseLike(x) {
     813         return x && typeof x.then === 'function';
     814     }
     815 
     816     /**
     817      * Initiates a competitive race, returning a promise that will resolve when
     818      * howMany of the supplied promisesOrValues have resolved, or will reject when
     819      * it becomes impossible for howMany to resolve, for example, when
     820      * (promisesOrValues.length - howMany) + 1 input promises reject.
     821      *
     822      * @param {Array} promisesOrValues array of anything, may contain a mix
     823      *      of promises and values
     824      * @param howMany {number} number of promisesOrValues to resolve
     825      * @param {function?} [onFulfilled] DEPRECATED, use returnedPromise.then()
     826      * @param {function?} [onRejected] DEPRECATED, use returnedPromise.then()
     827      * @param {function?} [onProgress] DEPRECATED, use returnedPromise.then()
     828      * @returns {Promise} promise that will resolve to an array of howMany values that
     829      *  resolved first, or will reject with an array of
     830      *  (promisesOrValues.length - howMany) + 1 rejection reasons.
     831      */
     832      // some是用来解决5个promise对象当有3个resolve时,就去执行onFulfilled
     833      // 如果超过3个reject时,就去执行onRejected
     834     function some(promisesOrValues, howMany, onFulfilled, onRejected, onProgress) {
     835 
     836         // 注意:之前就有说过when方法时可以传递promisesOrValues数组的
     837         return when(promisesOrValues, function(promisesOrValues) {
     838 
     839             return promise(resolveSome).then(onFulfilled, onRejected, onProgress);
     840 
     841             function resolveSome(resolve, reject, notify) {
     842                 var toResolve, toReject, values, reasons, fulfillOne, rejectOne, len, i;
     843 
     844                 len = promisesOrValues.length >>> 0;
     845                 // resolve的条件
     846                 toResolve = Math.max(0, Math.min(howMany, len));
     847                 values = [];
     848                 // reject的条件
     849                 toReject = (len - toResolve) + 1;
     850                 reasons = [];
     851 
     852                 // No items in the input, resolve immediately
     853                 // 空数组,直接resolve
     854                 if (!toResolve) {
     855                     resolve(values);
     856 
     857                 } else {
     858                     rejectOne = function(reason) {
     859                         // 保存reject的元素的reason信息
     860                         reasons.push(reason);
     861                         // 达到reject条件时
     862                         // 重置fulfillOne和rejectOne函数,不再保存接下来的数据
     863                         // 并reject返回的新创建的promise对象,以便执行onRejected回调
     864                         if(!--toReject) {
     865                             fulfillOne = rejectOne = identity;
     866                             reject(reasons);
     867                         }
     868                     };
     869 
     870                     fulfillOne = function(val) {
     871                         // This orders the values based on promise resolution order
     872                         // 保存resolve的元素的reason信息,顺序取决于各个promise对象的resolve的先后顺序
     873                         // 接下来与rejectOne差不多
     874                         values.push(val);
     875                         if (!--toResolve) {
     876                             fulfillOne = rejectOne = identity;
     877                             resolve(values);
     878                         }
     879                     };
     880                     // 遍历promisesOrValues数组
     881                     for(i = 0; i < len; ++i) {
     882                         if(i in promisesOrValues) {
     883                             when(promisesOrValues[i], fulfiller, rejecter, notify);
     884                         }
     885                     }
     886                 }
     887 
     888                 function rejecter(reason) {
     889                     rejectOne(reason);
     890                 }
     891 
     892                 function fulfiller(val) {
     893                     fulfillOne(val);
     894                 }
     895             }
     896         });
     897     }
     898 
     899     /**
     900      * Initiates a competitive race, returning a promise that will resolve when
     901      * any one of the supplied promisesOrValues has resolved or will reject when
     902      * *all* promisesOrValues have rejected.
     903      *
     904      * @param {Array|Promise} promisesOrValues array of anything, may contain a mix
     905      *      of {@link Promise}s and values
     906      * @param {function?} [onFulfilled] DEPRECATED, use returnedPromise.then()
     907      * @param {function?} [onRejected] DEPRECATED, use returnedPromise.then()
     908      * @param {function?} [onProgress] DEPRECATED, use returnedPromise.then()
     909      * @returns {Promise} promise that will resolve to the value that resolved first, or
     910      * will reject with an array of all rejected inputs.
     911      */
     912      // promisesOrValues数组中一个元素resolve那么执行onFulfilled,否则执行onRejected
     913      // 内部调用some函数,将参数howMany置为1
     914     function any(promisesOrValues, onFulfilled, onRejected, onProgress) {
     915 
     916         function unwrapSingleResult(val) {
     917             return onFulfilled ? onFulfilled(val[0]) : val[0];
     918         }
     919 
     920         return some(promisesOrValues, 1, unwrapSingleResult, onRejected, onProgress);
     921     }
     922 
     923     /**
     924      * Return a promise that will resolve only once all the supplied promisesOrValues
     925      * have resolved. The resolution value of the returned promise will be an array
     926      * containing the resolution values of each of the promisesOrValues.
     927      * @memberOf when
     928      *
     929      * @param {Array|Promise} promisesOrValues array of anything, may contain a mix
     930      *      of {@link Promise}s and values
     931      * @param {function?} [onFulfilled] DEPRECATED, use returnedPromise.then()
     932      * @param {function?} [onRejected] DEPRECATED, use returnedPromise.then()
     933      * @param {function?} [onProgress] DEPRECATED, use returnedPromise.then()
     934      * @returns {Promise}
     935      */
     936      // 与when.join功能几乎一样,就是传递参数的区别了,相见when.join
     937     function all(promisesOrValues, onFulfilled, onRejected, onProgress) {
     938         return _map(promisesOrValues, identity).then(onFulfilled, onRejected, onProgress);
     939     }
     940 
     941     /**
     942      * Joins multiple promises into a single returned promise.
     943      * @return {Promise} a promise that will fulfill when *all* the input promises
     944      * have fulfilled, or will reject when *any one* of the input promises rejects.
     945      */
     946      // when.join与when.map很想,都是调用_map,只不过它传递的时一个一个的promiseOrValue,
     947      // 内部通过arguments伪数组传递给_map
     948      // 而且指定函数为identity(返回每个resolve的value)
     949     function join(/* ...promises */) {
     950         return _map(arguments, identity);
     951     }
     952 
     953     /**
     954      * Settles all input promises such that they are guaranteed not to
     955      * be pending once the returned promise fulfills. The returned promise
     956      * will always fulfill, except in the case where `array` is a promise
     957      * that rejects.
     958      * @param {Array|Promise} array or promise for array of promises to settle
     959      * @returns {Promise} promise that always fulfills with an array of
     960      *  outcome snapshots for each input promise.
     961      */
     962      // 遍历promiseOrValue数组,返回的新promise对象一定会resolve,除非array本身就是rejected的promise对象
     963      // 且不会因为其中一个promise对象reject,而导致返回的新promise对象reject,而只会记录reject state的信息
     964      // 这与when.all方法时不同的
     965      // 可以看见内部调用了toFulfilledState和toRejectedState作为回调
     966      // 那么返回的promise对象在onFulfilled将得到数组所有promiseOrValue的state信息
     967     function settle(array) {
     968         return _map(array, toFulfilledState, toRejectedState);
     969     }
     970 
     971     /**
     972      * Promise-aware array map function, similar to `Array.prototype.map()`,
     973      * but input array may contain promises or values.
     974      * @param {Array|Promise} array array of anything, may contain promises and values
     975      * @param {function} mapFunc map function which may return a promise or value
     976      * @returns {Promise} promise that will fulfill with an array of mapped values
     977      *  or reject if any input promise rejects.
     978      */
     979      // 遍历promiseOrValue数组,如果数组每个元素都resolve,那么会将每个元素在调用mapFunc时的返回值
     980      // 保存在一个数组内,传递给返回的新的promise对象的onFulfilled方法,但是,如果有一个元素reject,
     981      // 那么返回的那个promise对象的onRejected被调用,并接受这个元素的reason
     982      // 如下:
     983     // when.map([defer.promise, defer2.promise, 'three'], function (value) {
     984     //     return value;
     985     // }).then(function (value) {
     986     //     console.log(value); // [ 'first', 'second', 'three' ]
     987     // }, function (reason) {
     988     //     console.log(reason);
     989     // });
     990     // defer.resolve('first');
     991     // defer2.resolve('second');
     992     function map(array, mapFunc) {
     993         return _map(array, mapFunc);
     994     }
     995 
     996     /**
     997      * Internal map that allows a fallback to handle rejections
     998      * @param {Array|Promise} array array of anything, may contain promises and values
     999      * @param {function} mapFunc map function which may return a promise or value
    1000      * @param {function?} fallback function to handle rejected promises
    1001      * @returns {Promise} promise that will fulfill with an array of mapped values
    1002      *  or reject if any input promise rejects.
    1003      */
    1004     function _map(array, mapFunc, fallback) {
    1005         // 这里array是一个promiseOrValue数组
    1006         return when(array, function(array) {
    1007             // 返回新的promise对象
    1008             return new Promise(resolveMap);
    1009 
    1010             function resolveMap(resolve, reject, notify) {
    1011                 var results, len, toResolve, i;
    1012 
    1013                 // Since we know the resulting length, we can preallocate the results
    1014                 // array to avoid array expansions.
    1015                 toResolve = len = array.length >>> 0;
    1016                 results = [];
    1017                 // 空数组直接返回
    1018                 if(!toResolve) {
    1019                     resolve(results);
    1020                     return;
    1021                 }
    1022 
    1023                 // Since mapFunc may be async, get all invocations of it into flight
    1024                 // 遍历数组内的promiseOrValue
    1025                 for(i = 0; i < len; i++) {
    1026                     // 数组元素验证,确保元素在数组内(数组也可以是伪数组)
    1027                     if(i in array) {
    1028 
    1029                         resolveOne(array[i], i);
    1030                     } else {
    1031                         --toResolve;
    1032                     }
    1033                 }
    1034 
    1035                 function resolveOne(item, i) {
    1036                     // 通过调用when方法将mapFunc(用户定义)函数的返回值存在results里,
    1037                     // 等最后toResolve为0时,一起传递给返回的新promise对象
    1038                     // 如果其中一个promise对象reject,那么reject返回的新promise对象
    1039                     // 返回值将是rejected的拿个promise对象的reason
    1040                     when(item, mapFunc, fallback).then(function(mapped) {
    1041                         // 保存每个promise对象的结果值
    1042                         results[i] = mapped;
    1043                         // 当所有promise对象都处理完了,resolve返回的新promise对象
    1044                         // 传递results数组
    1045                         if(!--toResolve) {
    1046                             resolve(results);
    1047                         }
    1048                     }, reject, notify);
    1049                 }
    1050             }
    1051         });
    1052     }
    1053 
    1054     /**
    1055      * Traditional reduce function, similar to `Array.prototype.reduce()`, but
    1056      * input may contain promises and/or values, and reduceFunc
    1057      * may return either a value or a promise, *and* initialValue may
    1058      * be a promise for the starting value.
    1059      *
    1060      * @param {Array|Promise} promise array or promise for an array of anything,
    1061      *      may contain a mix of promises and values.
    1062      * @param {function} reduceFunc reduce function reduce(currentValue, nextValue, index, total),
    1063      *      where total is the total number of items being reduced, and will be the same
    1064      *      in each call to reduceFunc.
    1065      * @returns {Promise} that will resolve to the final reduced value
    1066      */
    1067     function reduce(promise, reduceFunc /*, initialValue */) {
    1068         var args = fcall(slice, arguments, 1);
    1069 
    1070         return when(promise, function(array) {
    1071             var total;
    1072 
    1073             total = array.length;
    1074 
    1075             // Wrap the supplied reduceFunc with one that handles promises and then
    1076             // delegates to the supplied.
    1077             args[0] = function (current, val, i) {
    1078                 return when(current, function (c) {
    1079                     return when(val, function (value) {
    1080                         return reduceFunc(c, value, i, total);
    1081                     });
    1082                 });
    1083             };
    1084 
    1085             return reduceArray.apply(array, args);
    1086         });
    1087     }
    1088 
    1089     // Snapshot states
    1090 
    1091     /**
    1092      * Creates a fulfilled state snapshot
    1093      * @private
    1094      * @param {*} x any value
    1095      * @returns {{state:'fulfilled',value:*}}
    1096      */
    1097     function toFulfilledState(x) {
    1098         return { state: 'fulfilled', value: x };
    1099     }
    1100 
    1101     /**
    1102      * Creates a rejected state snapshot
    1103      * @private
    1104      * @param {*} x any reason
    1105      * @returns {{state:'rejected',reason:*}}
    1106      */
    1107     function toRejectedState(x) {
    1108         return { state: 'rejected', reason: x };
    1109     }
    1110 
    1111     /**
    1112      * Creates a pending state snapshot
    1113      * @private
    1114      * @returns {{state:'pending'}}
    1115      */
    1116     function toPendingState() {
    1117         return { state: 'pending' };
    1118     }
    1119 
    1120     //
    1121     // Internals, utilities, etc.
    1122     //
    1123 
    1124     var promisePrototype, makePromisePrototype, reduceArray, slice, fcall, nextTick, handlerQueue,
    1125         funcProto, call, arrayProto, monitorApi,
    1126         capturedSetTimeout, cjsRequire, MutationObs, undef;
    1127 
    1128     cjsRequire = require;
    1129 
    1130     //
    1131     // Shared handler queue processing
    1132     //
    1133     // Credit to Twisol (https://github.com/Twisol) for suggesting
    1134     // this type of extensible queue + trampoline approach for
    1135     // next-tick conflation.
    1136     // task队列
    1137     handlerQueue = [];
    1138 
    1139     /**
    1140      * Enqueue a task. If the queue is not currently scheduled to be
    1141      * drained, schedule it.
    1142      * @param {function} task
    1143      */
    1144      // 入队列,这里的进行了条件判断
    1145      // 原因在于在异步情况下可能出现很多次enqueue调用,那么我们只对第一次入队调用nextTick
    1146      // 下次时间周期自然会都被调用到
    1147     function enqueue(task) {
    1148         if(handlerQueue.push(task) === 1) {
    1149             nextTick(drainQueue);
    1150         }
    1151     }
    1152 
    1153     /**
    1154      * Drain the handler queue entirely, being careful to allow the
    1155      * queue to be extended while it is being processed, and to continue
    1156      * processing until it is truly empty.
    1157      */
    1158      // 出队列, 执行回调
    1159     function drainQueue() {
    1160         runHandlers(handlerQueue);
    1161         handlerQueue = [];
    1162     }
    1163 
    1164     // Allow attaching the monitor to when() if env has no console
    1165     monitorApi = typeof console !== 'undefined' ? console : when;
    1166 
    1167     // Sniff "best" async scheduling option
    1168     // Prefer process.nextTick or MutationObserver, then check for
    1169     // vertx and finally fall back to setTimeout
    1170     /*global process,document,setTimeout,MutationObserver,WebKitMutationObserver*/
    1171     // 以下是根据宿主环境采用不同的方式到达异步
    1172     // 优先是nodejs的process.nextTick
    1173     // 然后是MutationObserver
    1174     // 最后是setTimeout
    1175     // 这里异步的好处在于什么?为什么在reslove或者reject后,没有立即执行,而是加入队列,
    1176     // 这是因为中途的task还有可能加入,在下一个时间周期统一处理,会很方便,提高性能,而且这样充分利用
    1177     // javascript的单线程异步的特性,不会带来任何代码的阻塞问题
    1178     if (typeof process === 'object' && process.nextTick) {
    1179         nextTick = process.nextTick;
    1180     } else if(MutationObs =
    1181         (typeof MutationObserver === 'function' && MutationObserver) ||
    1182             (typeof WebKitMutationObserver === 'function' && WebKitMutationObserver)) {
    1183         nextTick = (function(document, MutationObserver, drainQueue) {
    1184             var el = document.createElement('div');
    1185             new MutationObserver(drainQueue).observe(el, { attributes: true });
    1186 
    1187             return function() {
    1188                 el.setAttribute('x', 'x');
    1189             };
    1190         }(document, MutationObs, drainQueue));
    1191     } else {
    1192         try {
    1193             // vert.x 1.x || 2.x
    1194             nextTick = cjsRequire('vertx').runOnLoop || cjsRequire('vertx').runOnContext;
    1195         } catch(ignore) {
    1196             // capture setTimeout to avoid being caught by fake timers
    1197             // used in time based tests
    1198             capturedSetTimeout = setTimeout;
    1199             nextTick = function(t) { capturedSetTimeout(t, 0); };
    1200         }
    1201     }
    1202 
    1203     //
    1204     // Capture/polyfill function and array utils
    1205     //
    1206 
    1207     // Safe function calls
    1208     funcProto = Function.prototype;
    1209     call = funcProto.call;
    1210     // 这里fcal的组合方式很有意思
    1211     // 看下兼容代码就能明白了
    1212     fcall = funcProto.bind
    1213         ? call.bind(call)
    1214         : function(f, context) {
    1215             return f.apply(context, slice.call(arguments, 2));
    1216         };
    1217 
    1218     // Safe array ops
    1219     arrayProto = [];
    1220     slice = arrayProto.slice;
    1221 
    1222     // ES5 reduce implementation if native not available
    1223     // See: http://es5.github.com/#x15.4.4.21 as there are many
    1224     // specifics and edge cases.  ES5 dictates that reduce.length === 1
    1225     // This implementation deviates from ES5 spec in the following ways:
    1226     // 1. It does not check if reduceFunc is a Callable
    1227     // 对[].reduce的兼容性处理
    1228     reduceArray = arrayProto.reduce ||
    1229         function(reduceFunc /*, initialValue */) {
    1230             /*jshint maxcomplexity: 7*/
    1231             var arr, args, reduced, len, i;
    1232 
    1233             i = 0;
    1234             arr = Object(this);
    1235             len = arr.length >>> 0;
    1236             args = arguments;
    1237 
    1238             // If no initialValue, use first item of array (we know length !== 0 here)
    1239             // and adjust i to start at second item
    1240             if(args.length <= 1) {
    1241                 // Skip to the first real element in the array
    1242                 for(;;) {
    1243                     if(i in arr) {
    1244                         reduced = arr[i++];
    1245                         break;
    1246                     }
    1247 
    1248                     // If we reached the end of the array without finding any real
    1249                     // elements, it's a TypeError
    1250                     if(++i >= len) {
    1251                         throw new TypeError();
    1252                     }
    1253                 }
    1254             } else {
    1255                 // If initialValue provided, use it
    1256                 reduced = args[1];
    1257             }
    1258 
    1259             // Do the actual reduce
    1260             for(;i < len; ++i) {
    1261                 if(i in arr) {
    1262                     reduced = reduceFunc(reduced, arr[i], i, arr);
    1263                 }
    1264             }
    1265 
    1266             return reduced;
    1267         };
    1268 
    1269     function identity(x) {
    1270         return x;
    1271     }
    1272 
    1273     function crash(fatalError) {
    1274         if(typeof monitorApi.reportUnhandled === 'function') {
    1275             monitorApi.reportUnhandled();
    1276         } else {
    1277             enqueue(function() {
    1278                 throw fatalError;
    1279             });
    1280         }
    1281 
    1282         throw fatalError;
    1283     }
    1284 
    1285     return when;
    1286 });
    1287 })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });

    晚安~~

  • 相关阅读:
    AppScan安全问题解决方案
    WPF方法 获取控件在屏幕的位置和自动控件位置
    WPF获取鼠标点击位置和API使用
    system.windows.controls
    .net 获取项目的根目录
    InvokeRequired
    控件取图片和矩形框 小测试
    mariadb 设置远程访问
    代码生成器 链接
    分享个网站
  • 原文地址:https://www.cnblogs.com/lovesueee/p/3507951.html
Copyright © 2011-2022 走看看