$.when()提供一种方法执行一个或多个函数的回调函数。如果传入一个延迟对象,则返回该对象的Promise对象,可以继续绑定其余回调,在执行结束状态之后也同时调用其when回调函数。如果传入多个延迟对象,则返回一个新的master延迟对象,跟踪所有的聚集状态,如果都成功解析完成,才调用其when回调函数;如果有一个失败,则全部失败,执行错误回调。
其使用方法:
$.when($.ajax("/page1.php"), $.ajax("/page2.php")) .then(myFunc, myFailure);其所有源码实现和注释为(能力有限,有些地方实在不能准确理解执行流程):
// 给when传递的对象绑定master.resolve和master.reject,用于聚集多异步对象的状态 function adoptValue( value, resolve, reject, noValue ) { var method; try { // Check for promise aspect first to privilege synchronous behavior // 如果when传入的参数promise方法可用,则封装promise并添加done和fail方法调用resolve和reject if ( value && jQuery.isFunction( ( method = value.promise ) ) ) { method.call( value ).done( resolve ).fail( reject ); // Other thenables // 否则,就判断传入参数的then方法是否可用,如果可用就传入resolve和reject方法 } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) { method.call( value, resolve, reject ); // Other non-thenables // 如果均不可用,则为非异步对象,直接resolve解析原值 } else { // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: // * false: [ value ].slice( 0 ) => resolve( value ) // * true: [ value ].slice( 1 ) => resolve() resolve.apply( undefined, [ value ].slice( noValue ) ); } // For Promises/A+, convert exceptions into rejections // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in // Deferred#then to conditionally suppress rejection. } catch ( value ) { // Support: Android 4.0 only // Strict mode functions invoked without .call/.apply get global-object context // 一个安卓4.0的bug,这里不做阐释 reject.apply( undefined, [ value ] ); } } // Deferred helper when: function( singleValue ) { var // count of uncompleted subordinates remaining = arguments.length, // count of unprocessed arguments i = remaining, // subordinate fulfillment data resolveContexts = Array( i ), resolveValues = slice.call( arguments ), // the master Deferred master = jQuery.Deferred(), // subordinate callback factory // 将每一个响应的环境和值都保存到列表里,在全部完成后统一传给主Promise用于执行 updateFunc = function( i ) { return function( value ) { resolveContexts[ i ] = this; resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; if ( !( --remaining ) ) { master.resolveWith( resolveContexts, resolveValues ); } }; }; // Single- and empty arguments are adopted like Promise.resolve // 如果只有一个参数,则直接将其作为master的回调 if ( remaining <= 1 ) { adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, !remaining ); // Use .then() to unwrap secondary thenables (cf. gh-3000) if ( master.state() === "pending" || jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { return master.then(); } } // Multiple arguments are aggregated like Promise.all array elements // 多参数时,进行所有参数的解析状态聚合到master上 while ( i-- ) { adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); } return master.promise(); }后续本来想把jQuery.Deferred和jQuery.ajax以及ES6的Promise对象给统一讲一下,结果发现牵涉的东西太多,每一个都可以单独写一篇文章,怕大家说太长不看,这里先写第一部分jQuery.Deferred吧,后续再补充另外两篇。