【原创】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); });

晚安~~

posted @ 2014-01-06 22:08  Lovesueee  阅读(2265)  评论(7编辑  收藏  举报