Repositorio del curso CCOM4030 el semestre B91 del proyecto Artesanías con el Instituto de Cultura

deferred.js 11KB

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