Blame view
app/bower_components/jquery/src/deferred.js
10.5 KB
87c93a029
|
1 |
define( [ |
f986e111b
|
2 3 4 5 |
"./core", "./var/slice", "./callbacks" ], function( jQuery, slice ) { |
87c93a029
|
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
"use strict"; function Identity( v ) { return v; } function Thrower( ex ) { throw ex; } function adoptValue( value, resolve, reject ) { var method; try { // Check for promise aspect first to privilege synchronous behavior if ( value && jQuery.isFunction( ( method = value.promise ) ) ) { method.call( value ).done( resolve ).fail( reject ); // Other thenables } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) { method.call( value, resolve, reject ); // Other non-thenables } else { // Support: Android 4.0 only // Strict mode functions invoked without .call/.apply get global-object context resolve.call( undefined, value ); } // 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 reject.call( undefined, value ); } } jQuery.extend( { |
f986e111b
|
48 49 50 |
Deferred: function( func ) { var tuples = [ |
87c93a029
|
51 52 53 54 55 56 57 58 59 |
// action, add listener, callbacks, // ... .then handlers, argument index, [final state] [ "notify", "progress", jQuery.Callbacks( "memory" ), jQuery.Callbacks( "memory" ), 2 ], [ "resolve", "done", jQuery.Callbacks( "once memory" ), jQuery.Callbacks( "once memory" ), 0, "resolved" ], [ "reject", "fail", jQuery.Callbacks( "once memory" ), jQuery.Callbacks( "once memory" ), 1, "rejected" ] |
f986e111b
|
60 61 62 63 64 65 66 67 68 69 |
], state = "pending", promise = { state: function() { return state; }, always: function() { deferred.done( arguments ).fail( arguments ); return this; }, |
87c93a029
|
70 71 72 73 74 75 |
"catch": function( fn ) { return promise.then( null, fn ); }, // Keep pipe for back-compat pipe: function( /* fnDone, fnFail, fnProgress */ ) { |
f986e111b
|
76 |
var fns = arguments; |
87c93a029
|
77 78 |
return jQuery.Deferred( function( newDefer ) { |
f986e111b
|
79 |
jQuery.each( tuples, function( i, tuple ) { |
87c93a029
|
80 81 82 83 84 85 86 87 |
// Map tuples (progress, done, fail) to arguments (done, fail, progress) var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; // deferred.progress(function() { bind to newDefer or newDefer.notify }) // deferred.done(function() { bind to newDefer or newDefer.resolve }) // deferred.fail(function() { bind to newDefer or newDefer.reject }) deferred[ tuple[ 1 ] ]( function() { |
f986e111b
|
88 89 90 |
var returned = fn && fn.apply( this, arguments ); if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise() |
87c93a029
|
91 |
.progress( newDefer.notify ) |
f986e111b
|
92 |
.done( newDefer.resolve ) |
87c93a029
|
93 |
.fail( newDefer.reject ); |
f986e111b
|
94 |
} else { |
87c93a029
|
95 96 97 98 |
newDefer[ tuple[ 0 ] + "With" ]( this, fn ? [ returned ] : arguments ); |
f986e111b
|
99 |
} |
87c93a029
|
100 101 |
} ); } ); |
f986e111b
|
102 |
fns = null; |
87c93a029
|
103 |
} ).promise(); |
f986e111b
|
104 |
}, |
87c93a029
|
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
then: function( onFulfilled, onRejected, onProgress ) { var maxDepth = 0; function resolve( depth, deferred, handler, special ) { return function() { var that = this, args = arguments, mightThrow = function() { var returned, then; // Support: Promises/A+ section 2.3.3.3.3 // https://promisesaplus.com/#point-59 // Ignore double-resolution attempts if ( depth < maxDepth ) { return; } returned = handler.apply( that, args ); // Support: Promises/A+ section 2.3.1 // https://promisesaplus.com/#point-48 if ( returned === deferred.promise() ) { throw new TypeError( "Thenable self-resolution" ); } // Support: Promises/A+ sections 2.3.3.1, 3.5 // https://promisesaplus.com/#point-54 // https://promisesaplus.com/#point-75 // Retrieve `then` only once then = returned && // Support: Promises/A+ section 2.3.4 // https://promisesaplus.com/#point-64 // Only check objects and functions for thenability ( typeof returned === "object" || typeof returned === "function" ) && returned.then; // Handle a returned thenable if ( jQuery.isFunction( then ) ) { // Special processors (notify) just wait for resolution if ( special ) { then.call( returned, resolve( maxDepth, deferred, Identity, special ), resolve( maxDepth, deferred, Thrower, special ) ); // Normal processors (resolve) also hook into progress } else { // ...and disregard older resolution values maxDepth++; then.call( returned, resolve( maxDepth, deferred, Identity, special ), resolve( maxDepth, deferred, Thrower, special ), resolve( maxDepth, deferred, Identity, deferred.notifyWith ) ); } // Handle all other returned values } else { // Only substitute handlers pass on context // and multiple values (non-spec behavior) if ( handler !== Identity ) { that = undefined; args = [ returned ]; } // Process the value(s) // Default process is resolve ( special || deferred.resolveWith )( that, args ); } }, // Only normal processors (resolve) catch and reject exceptions process = special ? mightThrow : function() { try { mightThrow(); } catch ( e ) { if ( jQuery.Deferred.exceptionHook ) { jQuery.Deferred.exceptionHook( e, process.stackTrace ); } // Support: Promises/A+ section 2.3.3.3.4.1 // https://promisesaplus.com/#point-61 // Ignore post-resolution exceptions if ( depth + 1 >= maxDepth ) { // Only substitute handlers pass on context // and multiple values (non-spec behavior) if ( handler !== Thrower ) { that = undefined; args = [ e ]; } deferred.rejectWith( that, args ); } } }; // Support: Promises/A+ section 2.3.3.3.1 // https://promisesaplus.com/#point-57 // Re-resolve promises immediately to dodge false rejection from // subsequent errors if ( depth ) { process(); } else { // Call an optional hook to record the stack, in case of exception // since it's otherwise lost when execution goes async if ( jQuery.Deferred.getStackHook ) { process.stackTrace = jQuery.Deferred.getStackHook(); } window.setTimeout( process ); } }; } return jQuery.Deferred( function( newDefer ) { // progress_handlers.add( ... ) tuples[ 0 ][ 3 ].add( resolve( 0, newDefer, jQuery.isFunction( onProgress ) ? onProgress : Identity, newDefer.notifyWith ) ); // fulfilled_handlers.add( ... ) tuples[ 1 ][ 3 ].add( resolve( 0, newDefer, jQuery.isFunction( onFulfilled ) ? onFulfilled : Identity ) ); // rejected_handlers.add( ... ) tuples[ 2 ][ 3 ].add( resolve( 0, newDefer, jQuery.isFunction( onRejected ) ? onRejected : Thrower ) ); } ).promise(); }, |
f986e111b
|
269 270 271 272 273 274 275 |
// Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise: function( obj ) { return obj != null ? jQuery.extend( obj, promise ) : promise; } }, deferred = {}; |
f986e111b
|
276 277 278 |
// Add list-specific methods jQuery.each( tuples, function( i, tuple ) { var list = tuple[ 2 ], |
87c93a029
|
279 |
stateString = tuple[ 5 ]; |
f986e111b
|
280 |
|
87c93a029
|
281 282 283 284 |
// promise.progress = list.add // promise.done = list.add // promise.fail = list.add promise[ tuple[ 1 ] ] = list.add; |
f986e111b
|
285 286 287 |
// Handle state if ( stateString ) { |
87c93a029
|
288 289 290 291 292 293 294 |
list.add( function() { // state = "resolved" (i.e., fulfilled) // state = "rejected" state = stateString; }, |
f986e111b
|
295 |
|
87c93a029
|
296 297 298 299 300 301 302 |
// rejected_callbacks.disable // fulfilled_callbacks.disable tuples[ 3 - i ][ 2 ].disable, // progress_callbacks.lock tuples[ 0 ][ 2 ].lock ); |
f986e111b
|
303 |
} |
87c93a029
|
304 305 306 307 308 309 310 311 312 313 |
// progress_handlers.fire // fulfilled_handlers.fire // rejected_handlers.fire list.add( tuple[ 3 ].fire ); // deferred.notify = function() { deferred.notifyWith(...) } // deferred.resolve = function() { deferred.resolveWith(...) } // deferred.reject = function() { deferred.rejectWith(...) } deferred[ tuple[ 0 ] ] = function() { deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); |
f986e111b
|
314 315 |
return this; }; |
87c93a029
|
316 317 318 319 320 321 |
// deferred.notifyWith = list.fireWith // deferred.resolveWith = list.fireWith // deferred.rejectWith = list.fireWith deferred[ tuple[ 0 ] + "With" ] = list.fireWith; } ); |
f986e111b
|
322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
// Make the deferred a promise promise.promise( deferred ); // Call given func if any if ( func ) { func.call( deferred, deferred ); } // All done! return deferred; }, // Deferred helper |
87c93a029
|
336 337 |
when: function( singleValue ) { var |
f986e111b
|
338 |
|
87c93a029
|
339 340 |
// count of uncompleted subordinates remaining = arguments.length, |
f986e111b
|
341 |
|
87c93a029
|
342 343 |
// count of unprocessed arguments i = remaining, |
f986e111b
|
344 |
|
87c93a029
|
345 346 347 |
// subordinate fulfillment data resolveContexts = Array( i ), resolveValues = slice.call( arguments ), |
f986e111b
|
348 |
|
87c93a029
|
349 350 351 352 353 354 355 356 357 358 |
// the master Deferred master = jQuery.Deferred(), // subordinate callback factory updateFunc = function( i ) { return function( value ) { resolveContexts[ i ] = this; resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; if ( !( --remaining ) ) { master.resolveWith( resolveContexts, resolveValues ); |
f986e111b
|
359 360 |
} }; |
87c93a029
|
361 |
}; |
f986e111b
|
362 |
|
87c93a029
|
363 364 365 366 367 368 369 370 371 |
// Single- and empty arguments are adopted like Promise.resolve if ( remaining <= 1 ) { adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject ); // Use .then() to unwrap secondary thenables (cf. gh-3000) if ( master.state() === "pending" || jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { return master.then(); |
f986e111b
|
372 373 |
} } |
87c93a029
|
374 375 376 |
// Multiple arguments are aggregated like Promise.all array elements while ( i-- ) { adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); |
f986e111b
|
377 |
} |
87c93a029
|
378 |
return master.promise(); |
f986e111b
|
379 |
} |
87c93a029
|
380 |
} ); |
f986e111b
|
381 382 |
return jQuery; |
87c93a029
|
383 |
} ); |