【原创】when.js2.7.1源码解析

时间:2022-01-13 15:48:40

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

解决这样的问题,可以是之前所说的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); });

晚安~~