@@ -247,143 +247,122 @@ function qFactory(nextTick, exceptionHandler) {
247
247
* @returns {Deferred } Returns a new instance of deferred.
248
248
*/
249
249
var defer = function ( ) {
250
- var pending = [ ] ,
251
- value , deferred ;
252
-
253
- deferred = {
254
-
255
- resolve : function ( val ) {
256
- if ( pending ) {
257
- var callbacks = pending ;
258
- pending = undefined ;
259
- value = ref ( val ) ;
260
-
261
- if ( callbacks . length ) {
262
- nextTick ( function ( ) {
263
- var callback ;
264
- for ( var i = 0 , ii = callbacks . length ; i < ii ; i ++ ) {
265
- callback = callbacks [ i ] ;
266
- value . then ( callback [ 0 ] , callback [ 1 ] , callback [ 2 ] ) ;
267
- }
268
- } ) ;
269
- }
270
- }
271
- } ,
272
-
273
-
274
- reject : function ( reason ) {
275
- deferred . resolve ( createInternalRejectedPromise ( reason ) ) ;
276
- } ,
250
+ return new Deferred ( ) ;
251
+ } ;
277
252
253
+ function Promise ( ) {
254
+ this . $$pending = [ ] ;
255
+ }
278
256
279
- notify : function ( progress ) {
280
- if ( pending ) {
281
- var callbacks = pending ;
257
+ Promise . prototype = {
258
+ then : function ( callback , errback , progressback ) {
259
+ var result = new Deferred ( ) ;
282
260
283
- if ( pending . length ) {
284
- nextTick ( function ( ) {
285
- var callback ;
286
- for ( var i = 0 , ii = callbacks . length ; i < ii ; i ++ ) {
287
- callback = callbacks [ i ] ;
288
- callback [ 2 ] ( progress ) ;
289
- }
290
- } ) ;
291
- }
261
+ var wrappedCallback = function ( value ) {
262
+ try {
263
+ result . resolve ( ( isFunction ( callback ) ? callback : defaultCallback ) ( value ) ) ;
264
+ } catch ( e ) {
265
+ result . reject ( e ) ;
266
+ exceptionHandler ( e ) ;
292
267
}
293
- } ,
294
-
295
-
296
- promise : {
297
- then : function ( callback , errback , progressback ) {
298
- var result = defer ( ) ;
299
-
300
- var wrappedCallback = function ( value ) {
301
- try {
302
- result . resolve ( ( isFunction ( callback ) ? callback : defaultCallback ) ( value ) ) ;
303
- } catch ( e ) {
304
- result . reject ( e ) ;
305
- exceptionHandler ( e ) ;
306
- }
307
- } ;
308
-
309
- var wrappedErrback = function ( reason ) {
310
- try {
311
- result . resolve ( ( isFunction ( errback ) ? errback : defaultErrback ) ( reason ) ) ;
312
- } catch ( e ) {
313
- result . reject ( e ) ;
314
- exceptionHandler ( e ) ;
315
- }
316
- } ;
317
-
318
- var wrappedProgressback = function ( progress ) {
319
- try {
320
- result . notify ( ( isFunction ( progressback ) ? progressback : defaultCallback ) ( progress ) ) ;
321
- } catch ( e ) {
322
- exceptionHandler ( e ) ;
323
- }
324
- } ;
268
+ } ;
269
+
270
+ var wrappedErrback = function ( reason ) {
271
+ try {
272
+ result . resolve ( ( isFunction ( errback ) ? errback : defaultErrback ) ( reason ) ) ;
273
+ } catch ( e ) {
274
+ result . reject ( e ) ;
275
+ exceptionHandler ( e ) ;
276
+ }
277
+ } ;
325
278
326
- if ( pending ) {
327
- pending . push ( [ wrappedCallback , wrappedErrback , wrappedProgressback ] ) ;
328
- } else {
329
- value . then ( wrappedCallback , wrappedErrback , wrappedProgressback ) ;
330
- }
279
+ var wrappedProgressback = function ( progress ) {
280
+ try {
281
+ result . notify ( ( isFunction ( progressback ) ? progressback : defaultCallback ) ( progress ) ) ;
282
+ } catch ( e ) {
283
+ exceptionHandler ( e ) ;
284
+ }
285
+ } ;
331
286
332
- return result . promise ;
333
- } ,
287
+ if ( this . $$pending ) {
288
+ this . $$pending . push ( [ wrappedCallback , wrappedErrback , wrappedProgressback ] ) ;
289
+ } else {
290
+ this . $$value . then ( wrappedCallback , wrappedErrback , wrappedProgressback ) ;
291
+ }
334
292
335
- "catch" : function ( callback ) {
336
- return this . then ( null , callback ) ;
337
- } ,
293
+ return result . promise ;
294
+ } ,
295
+
296
+ "catch" : function ( callback ) {
297
+ return this . then ( null , callback ) ;
298
+ } ,
299
+ "finally" : function ( callback ) {
300
+ return this . then ( function ( value ) {
301
+ return handleCallback ( value , true , callback ) ;
302
+ } , function ( error ) {
303
+ return handleCallback ( error , false , callback ) ;
304
+ } ) ;
305
+ }
306
+ } ;
338
307
339
- "finally" : function ( callback ) {
308
+ //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native
309
+ function simpleBind ( context , fn ) {
310
+ return function ( value ) {
311
+ fn . call ( context , value ) ;
312
+ } ;
313
+ }
340
314
341
- function makePromise ( value , resolved ) {
342
- var result = defer ( ) ;
343
- if ( resolved ) {
344
- result . resolve ( value ) ;
345
- } else {
346
- result . reject ( value ) ;
347
- }
348
- return result . promise ;
349
- }
315
+ function Deferred ( ) {
316
+ this . promise = new Promise ( ) ;
317
+ //Necessary to support unbound execution :/
318
+ this . resolve = simpleBind ( this , this . resolve ) ;
319
+ this . reject = simpleBind ( this , this . reject ) ;
320
+ this . notify = simpleBind ( this , this . notify ) ;
321
+ }
350
322
351
- function handleCallback ( value , isResolved ) {
352
- var callbackOutput = null ;
353
- try {
354
- callbackOutput = ( callback || defaultCallback ) ( ) ;
355
- } catch ( e ) {
356
- return makePromise ( e , false ) ;
323
+ Deferred . prototype = {
324
+ resolve : function ( val ) {
325
+ if ( this . promise . $$pending ) {
326
+ var callbacks = this . promise . $$pending ;
327
+ this . promise . $$pending = undefined ;
328
+ this . promise . $$value = ref ( val ) ;
329
+
330
+ if ( callbacks . length ) {
331
+ nextTick ( simpleBind ( this , function ( ) {
332
+ var callback ;
333
+ for ( var i = 0 , ii = callbacks . length ; i < ii ; i ++ ) {
334
+ callback = callbacks [ i ] ;
335
+ this . promise . $$value . then ( callback [ 0 ] , callback [ 1 ] , callback [ 2 ] ) ;
357
336
}
358
- if ( isPromiseLike ( callbackOutput ) ) {
359
- return callbackOutput . then ( function ( ) {
360
- return makePromise ( value , isResolved ) ;
361
- } , function ( error ) {
362
- return makePromise ( error , false ) ;
363
- } ) ;
364
- } else {
365
- return makePromise ( value , isResolved ) ;
337
+ } ) ) ;
338
+ }
339
+ }
340
+ } ,
341
+ reject : function ( reason ) {
342
+ this . resolve ( createInternalRejectedPromise ( reason ) ) ;
343
+ } ,
344
+ notify : function ( progress ) {
345
+ if ( this . promise . $$pending ) {
346
+ var callbacks = this . promise . $$pending ;
347
+
348
+ if ( this . promise . $$pending . length ) {
349
+ nextTick ( function ( ) {
350
+ var callback ;
351
+ for ( var i = 0 , ii = callbacks . length ; i < ii ; i ++ ) {
352
+ callback = callbacks [ i ] ;
353
+ callback [ 2 ] ( progress ) ;
366
354
}
367
- }
368
-
369
- return this . then ( function ( value ) {
370
- return handleCallback ( value , true ) ;
371
- } , function ( error ) {
372
- return handleCallback ( error , false ) ;
373
355
} ) ;
374
356
}
375
357
}
376
- } ;
377
-
378
- return deferred ;
358
+ }
379
359
} ;
380
360
381
-
382
361
var ref = function ( value ) {
383
362
if ( isPromiseLike ( value ) ) return value ;
384
363
return {
385
364
then : function ( callback ) {
386
- var result = defer ( ) ;
365
+ var result = new Deferred ( ) ;
387
366
nextTick ( function ( ) {
388
367
result . resolve ( callback ( value ) ) ;
389
368
} ) ;
@@ -430,15 +409,43 @@ function qFactory(nextTick, exceptionHandler) {
430
409
* @returns {Promise } Returns a promise that was already resolved as rejected with the `reason`.
431
410
*/
432
411
var reject = function ( reason ) {
433
- var result = defer ( ) ;
412
+ var result = new Deferred ( ) ;
434
413
result . reject ( reason ) ;
435
414
return result . promise ;
436
415
} ;
437
416
417
+ var makePromise = function makePromise ( value , resolved ) {
418
+ var result = new Deferred ( ) ;
419
+ if ( resolved ) {
420
+ result . resolve ( value ) ;
421
+ } else {
422
+ result . reject ( value ) ;
423
+ }
424
+ return result . promise ;
425
+ } ;
426
+
427
+ var handleCallback = function handleCallback ( value , isResolved , callback ) {
428
+ var callbackOutput = null ;
429
+ try {
430
+ callbackOutput = ( callback || defaultCallback ) ( ) ;
431
+ } catch ( e ) {
432
+ return makePromise ( e , false ) ;
433
+ }
434
+ if ( isPromiseLike ( callbackOutput ) ) {
435
+ return callbackOutput . then ( function ( ) {
436
+ return makePromise ( value , isResolved ) ;
437
+ } , function ( error ) {
438
+ return makePromise ( error , false ) ;
439
+ } ) ;
440
+ } else {
441
+ return makePromise ( value , isResolved ) ;
442
+ }
443
+ } ;
444
+
438
445
var createInternalRejectedPromise = function ( reason ) {
439
446
return {
440
447
then : function ( callback , errback ) {
441
- var result = defer ( ) ;
448
+ var result = new Deferred ( ) ;
442
449
nextTick ( function ( ) {
443
450
try {
444
451
result . resolve ( ( isFunction ( errback ) ? errback : defaultErrback ) ( reason ) ) ;
@@ -467,7 +474,7 @@ function qFactory(nextTick, exceptionHandler) {
467
474
* @returns {Promise } Returns a promise of the passed value or promise
468
475
*/
469
476
var when = function ( value , callback , errback , progressback ) {
470
- var result = defer ( ) ,
477
+ var result = new Deferred ( ) ,
471
478
done ;
472
479
473
480
var wrappedCallback = function ( value ) {
@@ -541,7 +548,7 @@ function qFactory(nextTick, exceptionHandler) {
541
548
* with the same rejection value.
542
549
*/
543
550
function all ( promises ) {
544
- var deferred = defer ( ) ,
551
+ var deferred = new Deferred ( ) ,
545
552
counter = 0 ,
546
553
results = isArray ( promises ) ? [ ] : { } ;
547
554
@@ -575,7 +582,7 @@ function qFactory(nextTick, exceptionHandler) {
575
582
return new Q ( resolver ) ;
576
583
}
577
584
578
- var deferred = defer ( ) ;
585
+ var deferred = new Deferred ( ) ;
579
586
580
587
function resolveFn ( value ) {
581
588
deferred . resolve ( value ) ;
0 commit comments