From 63a834decf28fbbd5d2eb128c4ce1bbf8a3a61c4 Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Tue, 10 Nov 2015 21:18:30 -0800 Subject: [PATCH 1/2] perf($q): only bind Deferred methods when returned publicly from $q.defer --- src/ng/q.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ng/q.js b/src/ng/q.js index 8bb9536b6672..a3dcff896a95 100644 --- a/src/ng/q.js +++ b/src/ng/q.js @@ -267,7 +267,12 @@ function qFactory(nextTick, exceptionHandler) { * @returns {Deferred} Returns a new instance of deferred. */ var defer = function() { - return new Deferred(); + var d = new Deferred(); + //Necessary to support unbound execution :/ + d.resolve = simpleBind(d, d.resolve); + d.reject = simpleBind(d, d.reject); + d.notify = simpleBind(d, d.notify); + return d; }; function Promise() { @@ -340,10 +345,6 @@ function qFactory(nextTick, exceptionHandler) { function Deferred() { this.promise = new Promise(); - //Necessary to support unbound execution :/ - this.resolve = simpleBind(this, this.resolve); - this.reject = simpleBind(this, this.reject); - this.notify = simpleBind(this, this.notify); } extend(Deferred.prototype, { @@ -368,7 +369,7 @@ function qFactory(nextTick, exceptionHandler) { if ((isObject(val) || isFunction(val))) then = val && val.then; if (isFunction(then)) { this.promise.$$state.status = -1; - then.call(val, fns[0], fns[1], this.notify); + then.call(val, fns[0], fns[1], simpleBind(this, this.notify)); } else { this.promise.$$state.value = val; this.promise.$$state.status = 1; From 3621d92f9a95bdfc712f31f7d2e5599e85ce87ad Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Tue, 17 Nov 2015 01:49:27 -0800 Subject: [PATCH 2/2] perf($q): reduce closures when resolving promises - changes Deferred.$$resolve to only wrap the internal resolve/reject when wrapping another promise --- src/ng/q.js | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/ng/q.js b/src/ng/q.js index a3dcff896a95..c33169d18d27 100644 --- a/src/ng/q.js +++ b/src/ng/q.js @@ -243,18 +243,6 @@ function $$QProvider() { */ function qFactory(nextTick, exceptionHandler) { var $qMinErr = minErr('$q', TypeError); - function callOnce(self, resolveFn, rejectFn) { - var called = false; - function wrap(fn) { - return function(value) { - if (called) return; - called = true; - fn.call(self, value); - }; - } - - return [wrap(resolveFn), wrap(rejectFn)]; - } /** * @ngdoc method @@ -362,23 +350,34 @@ function qFactory(nextTick, exceptionHandler) { }, $$resolve: function(val) { - var then, fns; - - fns = callOnce(this, this.$$resolve, this.$$reject); + var then; + var that = this; + var done = false; try { if ((isObject(val) || isFunction(val))) then = val && val.then; if (isFunction(then)) { this.promise.$$state.status = -1; - then.call(val, fns[0], fns[1], simpleBind(this, this.notify)); + then.call(val, resolvePromise, rejectPromise, simpleBind(this, this.notify)); } else { this.promise.$$state.value = val; this.promise.$$state.status = 1; scheduleProcessQueue(this.promise.$$state); } } catch (e) { - fns[1](e); + rejectPromise(e); exceptionHandler(e); } + + function resolvePromise(val) { + if (done) return; + done = true; + that.$$resolve(val); + } + function rejectPromise(val) { + if (done) return; + done = true; + that.$$reject(val); + } }, reject: function(reason) {