@@ -247,143 +247,122 @@ function qFactory(nextTick, exceptionHandler) {
247247 * @returns {Deferred } Returns a new instance of deferred.
248248 */
249249 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+ } ;
277252
253+ function Promise ( ) {
254+ this . $$pending = [ ] ;
255+ }
278256
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 ( ) ;
282260
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 ) ;
292267 }
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+ } ;
325278
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+ } ;
331286
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+ }
334292
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+ } ;
338307
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+ }
340314
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+ }
350322
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 ] ) ;
357336 }
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 ) ;
366354 }
367- }
368-
369- return this . then ( function ( value ) {
370- return handleCallback ( value , true ) ;
371- } , function ( error ) {
372- return handleCallback ( error , false ) ;
373355 } ) ;
374356 }
375357 }
376- } ;
377-
378- return deferred ;
358+ }
379359 } ;
380360
381-
382361 var ref = function ( value ) {
383362 if ( isPromiseLike ( value ) ) return value ;
384363 return {
385364 then : function ( callback ) {
386- var result = defer ( ) ;
365+ var result = new Deferred ( ) ;
387366 nextTick ( function ( ) {
388367 result . resolve ( callback ( value ) ) ;
389368 } ) ;
@@ -430,15 +409,43 @@ function qFactory(nextTick, exceptionHandler) {
430409 * @returns {Promise } Returns a promise that was already resolved as rejected with the `reason`.
431410 */
432411 var reject = function ( reason ) {
433- var result = defer ( ) ;
412+ var result = new Deferred ( ) ;
434413 result . reject ( reason ) ;
435414 return result . promise ;
436415 } ;
437416
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+
438445 var createInternalRejectedPromise = function ( reason ) {
439446 return {
440447 then : function ( callback , errback ) {
441- var result = defer ( ) ;
448+ var result = new Deferred ( ) ;
442449 nextTick ( function ( ) {
443450 try {
444451 result . resolve ( ( isFunction ( errback ) ? errback : defaultErrback ) ( reason ) ) ;
@@ -467,7 +474,7 @@ function qFactory(nextTick, exceptionHandler) {
467474 * @returns {Promise } Returns a promise of the passed value or promise
468475 */
469476 var when = function ( value , callback , errback , progressback ) {
470- var result = defer ( ) ,
477+ var result = new Deferred ( ) ,
471478 done ;
472479
473480 var wrappedCallback = function ( value ) {
@@ -541,7 +548,7 @@ function qFactory(nextTick, exceptionHandler) {
541548 * with the same rejection value.
542549 */
543550 function all ( promises ) {
544- var deferred = defer ( ) ,
551+ var deferred = new Deferred ( ) ,
545552 counter = 0 ,
546553 results = isArray ( promises ) ? [ ] : { } ;
547554
@@ -575,7 +582,7 @@ function qFactory(nextTick, exceptionHandler) {
575582 return new Q ( resolver ) ;
576583 }
577584
578- var deferred = defer ( ) ;
585+ var deferred = new Deferred ( ) ;
579586
580587 function resolveFn ( value ) {
581588 deferred . resolve ( value ) ;
0 commit comments