Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit a04bf03

Browse files
committed
refactor($q): separate Promise from Deferred
1 parent 16dccea commit a04bf03

File tree

1 file changed

+98
-105
lines changed

1 file changed

+98
-105
lines changed

src/ng/q.js

+98-105
Original file line numberDiff line numberDiff line change
@@ -299,14 +299,18 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {
299299
* @returns {Deferred} Returns a new instance of deferred.
300300
*/
301301
function defer() {
302-
var d = new Deferred();
303-
//Necessary to support unbound execution :/
304-
d.resolve = simpleBind(d, d.resolve);
305-
d.reject = simpleBind(d, d.reject);
306-
d.notify = simpleBind(d, d.notify);
307-
return d;
302+
return new Deferred();
308303
}
309304

305+
function Deferred() {
306+
var promise = this.promise = new Promise();
307+
//Non prototype methods necessary to support unbound execution :/
308+
this.resolve = function(val) { resolvePromise(promise, val); };
309+
this.reject = function(reason) { rejectPromise(promise, reason); };
310+
this.notify = function(progress) { notifyPromise(promise, progress); };
311+
}
312+
313+
310314
function Promise() {
311315
this.$$state = { status: 0 };
312316
}
@@ -316,13 +320,13 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {
316320
if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) {
317321
return this;
318322
}
319-
var result = new Deferred();
323+
var result = new Promise();
320324

321325
this.$$state.pending = this.$$state.pending || [];
322326
this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);
323327
if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);
324328

325-
return result.promise;
329+
return result;
326330
},
327331

328332
'catch': function(callback) {
@@ -338,34 +342,27 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {
338342
}
339343
});
340344

341-
//Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native
342-
function simpleBind(context, fn) {
343-
return function(value) {
344-
fn.call(context, value);
345-
};
346-
}
347-
348345
function processQueue(state) {
349-
var fn, deferred, pending;
346+
var fn, promise, pending;
350347

351348
pending = state.pending;
352349
state.processScheduled = false;
353350
state.pending = undefined;
354351
try {
355352
for (var i = 0, ii = pending.length; i < ii; ++i) {
356353
state.pur = true;
357-
deferred = pending[i][0];
354+
promise = pending[i][0];
358355
fn = pending[i][state.status];
359356
try {
360357
if (isFunction(fn)) {
361-
deferred.resolve(fn(state.value));
358+
resolvePromise(promise, fn(state.value));
362359
} else if (state.status === 1) {
363-
deferred.resolve(state.value);
360+
resolvePromise(promise, state.value);
364361
} else {
365-
deferred.reject(state.value);
362+
rejectPromise(promise, state.value);
366363
}
367364
} catch (e) {
368-
deferred.reject(e);
365+
rejectPromise(promise, e);
369366
exceptionHandler(e);
370367
}
371368
}
@@ -402,85 +399,81 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {
402399
nextTick(function() { processQueue(state); });
403400
}
404401

405-
function Deferred() {
406-
this.promise = new Promise();
402+
function resolvePromise(promise, val) {
403+
if (promise.$$state.status) return;
404+
if (val === promise) {
405+
$$reject(promise, $qMinErr(
406+
'qcycle',
407+
'Expected promise to be resolved with value other than itself \'{0}\'',
408+
val));
409+
} else {
410+
$$resolve(promise, val);
411+
}
412+
407413
}
408414

409-
extend(Deferred.prototype, {
410-
resolve: function(val) {
411-
if (this.promise.$$state.status) return;
412-
if (val === this.promise) {
413-
this.$$reject($qMinErr(
414-
'qcycle',
415-
'Expected promise to be resolved with value other than itself \'{0}\'',
416-
val));
415+
function $$resolve(promise, val) {
416+
var then;
417+
var done = false;
418+
try {
419+
if ((isObject(val) || isFunction(val))) then = val && val.then;
420+
if (isFunction(then)) {
421+
promise.$$state.status = -1;
422+
then.call(val, doResolve, doReject, doNotify);
417423
} else {
418-
this.$$resolve(val);
419-
}
420-
421-
},
422-
423-
$$resolve: function(val) {
424-
var then;
425-
var that = this;
426-
var done = false;
427-
try {
428-
if ((isObject(val) || isFunction(val))) then = val && val.then;
429-
if (isFunction(then)) {
430-
this.promise.$$state.status = -1;
431-
then.call(val, resolvePromise, rejectPromise, simpleBind(this, this.notify));
432-
} else {
433-
this.promise.$$state.value = val;
434-
this.promise.$$state.status = 1;
435-
scheduleProcessQueue(this.promise.$$state);
436-
}
437-
} catch (e) {
438-
rejectPromise(e);
439-
exceptionHandler(e);
424+
promise.$$state.value = val;
425+
promise.$$state.status = 1;
426+
scheduleProcessQueue(promise.$$state);
440427
}
428+
} catch (e) {
429+
doReject(e);
430+
exceptionHandler(e);
431+
}
441432

442-
function resolvePromise(val) {
443-
if (done) return;
444-
done = true;
445-
that.$$resolve(val);
446-
}
447-
function rejectPromise(val) {
448-
if (done) return;
449-
done = true;
450-
that.$$reject(val);
451-
}
452-
},
433+
function doResolve(val) {
434+
if (done) return;
435+
done = true;
436+
$$resolve(promise, val);
437+
}
438+
function doReject(val) {
439+
if (done) return;
440+
done = true;
441+
$$reject(promise, val);
442+
}
443+
function doNotify(progress) {
444+
notifyPromise(promise, progress);
445+
}
446+
}
453447

454-
reject: function(reason) {
455-
if (this.promise.$$state.status) return;
456-
this.$$reject(reason);
457-
},
448+
function rejectPromise(promise, reason) {
449+
if (promise.$$state.status) return;
450+
$$reject(promise, reason);
451+
}
458452

459-
$$reject: function(reason) {
460-
this.promise.$$state.value = reason;
461-
this.promise.$$state.status = 2;
462-
scheduleProcessQueue(this.promise.$$state);
463-
},
453+
function $$reject(promise, reason) {
454+
promise.$$state.value = reason;
455+
promise.$$state.status = 2;
456+
scheduleProcessQueue(promise.$$state);
457+
}
464458

465-
notify: function(progress) {
466-
var callbacks = this.promise.$$state.pending;
467-
468-
if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {
469-
nextTick(function() {
470-
var callback, result;
471-
for (var i = 0, ii = callbacks.length; i < ii; i++) {
472-
result = callbacks[i][0];
473-
callback = callbacks[i][3];
474-
try {
475-
result.notify(isFunction(callback) ? callback(progress) : progress);
476-
} catch (e) {
477-
exceptionHandler(e);
478-
}
459+
function notifyPromise(promise, progress) {
460+
var callbacks = promise.$$state.pending;
461+
462+
if ((promise.$$state.status <= 0) && callbacks && callbacks.length) {
463+
nextTick(function() {
464+
var callback, result;
465+
for (var i = 0, ii = callbacks.length; i < ii; i++) {
466+
result = callbacks[i][0];
467+
callback = callbacks[i][3];
468+
try {
469+
notifyPromise(result, isFunction(callback) ? callback(progress) : progress);
470+
} catch (e) {
471+
exceptionHandler(e);
479472
}
480-
});
481-
}
473+
}
474+
});
482475
}
483-
});
476+
}
484477

485478
/**
486479
* @ngdoc method
@@ -519,9 +512,9 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {
519512
* @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
520513
*/
521514
function reject(reason) {
522-
var result = new Deferred();
523-
result.reject(reason);
524-
return result.promise;
515+
var result = new Promise();
516+
rejectPromise(result, reason);
517+
return result;
525518
}
526519

527520
function handleCallback(value, resolver, callback) {
@@ -559,9 +552,9 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {
559552

560553

561554
function when(value, callback, errback, progressBack) {
562-
var result = new Deferred();
563-
result.resolve(value);
564-
return result.promise.then(callback, errback, progressBack);
555+
var result = new Promise();
556+
resolvePromise(result, value);
557+
return result.then(callback, errback, progressBack);
565558
}
566559

567560
/**
@@ -597,25 +590,25 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {
597590
*/
598591

599592
function all(promises) {
600-
var deferred = new Deferred(),
593+
var result = new Promise(),
601594
counter = 0,
602595
results = isArray(promises) ? [] : {};
603596

604597
forEach(promises, function(promise, key) {
605598
counter++;
606599
when(promise).then(function(value) {
607600
results[key] = value;
608-
if (!(--counter)) deferred.resolve(results);
601+
if (!(--counter)) resolvePromise(result, results);
609602
}, function(reason) {
610-
deferred.reject(reason);
603+
rejectPromise(result, reason);
611604
});
612605
});
613606

614607
if (counter === 0) {
615-
deferred.resolve(results);
608+
resolvePromise(result, results);
616609
}
617610

618-
return deferred.promise;
611+
return result;
619612
}
620613

621614
/**
@@ -647,19 +640,19 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {
647640
throw $qMinErr('norslvr', 'Expected resolverFn, got \'{0}\'', resolver);
648641
}
649642

650-
var deferred = new Deferred();
643+
var promise = new Promise();
651644

652645
function resolveFn(value) {
653-
deferred.resolve(value);
646+
resolvePromise(promise, value);
654647
}
655648

656649
function rejectFn(reason) {
657-
deferred.reject(reason);
650+
rejectPromise(promise, reason);
658651
}
659652

660653
resolver(resolveFn, rejectFn);
661654

662-
return deferred.promise;
655+
return promise;
663656
}
664657

665658
// Let's make the instanceof operator work for promises, so that

0 commit comments

Comments
 (0)