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

Commit bb3be87

Browse files
committed
style(q): reorganize the file + drop fallback dependencies
1 parent 174952e commit bb3be87

File tree

1 file changed

+137
-123
lines changed

1 file changed

+137
-123
lines changed

src/Deferred.js

+137-123
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,148 @@
11
'use strict';
22

33
/**
4-
* Constructs a promise manager.
4+
* @ngdoc service
5+
* @name angular.module.ng.$q
6+
* @requires $rootScope
57
*
6-
* @param {function(function)=} nextTick Function for executing functions in the next turn. Falls
7-
* back to `setTimeout` if undefined.
8-
* @param {function(...*)=} exceptionHandler Function into which unexpected exceptions are passed for
9-
* debugging purposes. Falls back to `console.error` if undefined,
10-
* @returns {object} Promise manager.
8+
* @description
9+
* A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).
10+
*
11+
* [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
12+
* interface for interacting with an object that represents the result of an action that is
13+
* performed asynchronously, and may or may not be finished at any given point in time.
14+
*
15+
* From the perspective of dealing with error handling, deferred and promise apis are to
16+
* asynchronous programing what `try`, `catch` and `throw` keywords are to synchronous programing.
17+
*
18+
* <pre>
19+
* // for the purpose of this example let's assume that variables `$q` and `scope` are
20+
* // available in the current lexical scope (they could have been injected or passed in).
21+
*
22+
* function asyncGreet(name) {
23+
* var deferred = $q.defer();
24+
*
25+
* setTimeout(function() {
26+
* // since this fn executes async in a future turn of the event loop, we need to wrap
27+
* // our code into an $apply call so that the model changes are properly observed.
28+
* scope.$apply(function() {
29+
* if (okToGreet(name)) {
30+
* deferred.resolve('Hello, ' + name + '!');
31+
* } else {
32+
* deferred.reject('Greeting ' + name + ' is not allowed.');
33+
* }
34+
* });
35+
* }, 1000);
36+
*
37+
* return deferred.promise;
38+
* }
39+
*
40+
* var promise = asyncGreet('Robin Hood');
41+
* promise.then(function(greeting) {
42+
* alert('Success: ' + greeting);
43+
* }, function(reason) {
44+
* alert('Failed: ' + reason);
45+
* );
46+
* </pre>
47+
*
48+
* At first it might not be obvious why this extra complexity is worth the trouble. The payoff
49+
* comes in the way of
50+
* [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).
51+
*
52+
* Additionally the promise api allows for composition that is very hard to do with the
53+
* traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
54+
* For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
55+
* section on serial or parallel joining of promises.
56+
*
57+
*
58+
* # The Deferred API
59+
*
60+
* A new instance of deferred is constructed by calling `$q.defer()`.
61+
*
62+
* The purpose of the deferred object is to expose the associated Promise instance as well as apis
63+
* that can be used for signaling the successful or unsuccessful completion of the task.
64+
*
65+
* **Methods**
66+
*
67+
* - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
68+
* constructed via `$q.reject`, the promise will be rejected instead.
69+
* - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
70+
* resolving it with a rejection constructed via `$q.reject`.
71+
*
72+
* **Properties**
73+
*
74+
* - promise – `{Promise}` – promise object associated with this deferred.
75+
*
76+
*
77+
* # The Promise API
78+
*
79+
* A new promise instance is created when a deferred instance is created and can be retrieved by
80+
* calling `deferred.promise`.
81+
*
82+
* The purpose of the promise object is to allow for interested parties to get access to the result
83+
* of the deferred task when it completes.
84+
*
85+
* **Methods**
86+
*
87+
* - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved
88+
* or rejected calls one of the success or error callbacks asynchronously as soon as the result
89+
* is available. The callbacks are called with a single argument the result or rejection reason.
90+
*
91+
* This method *returns a new promise* which is resolved or rejected via the return value of the
92+
* `successCallback` or `errorCallback`.
93+
*
94+
*
95+
* # Chaining promises
96+
*
97+
* Because calling `then` api of a promise returns a new derived promise, it is easily possible
98+
* to create a chain of promises:
99+
*
100+
* <pre>
101+
* promiseB = promiseA.then(function(result) {
102+
* return result + 1;
103+
* });
104+
*
105+
* // promiseB will be resolved immediately after promiseA is resolved and it's value will be
106+
* // the result of promiseA incremented by 1
107+
* </pre>
108+
*
109+
* It is possible to create chains of any length and since a promise can be resolved with another
110+
* promise (which will defer its resolution further), it is possible to pause/defer resolution of
111+
* the promises at any point in the chain. This makes it possible to implement powerful apis like
112+
* $http's response interceptors.
113+
*
114+
*
115+
* # Differences between Kris Kowal's Q and $q
116+
*
117+
* There are three main differences:
118+
*
119+
* - $q is integrated with the {@link angular.module.ng.$rootScope.Scope} Scope model observation
120+
* mechanism in angular, which means faster propagation of resolution or rejection into your
121+
* models and avoiding unnecessary browser repaints, which would result in flickering UI.
122+
* - $q promises are recognized by the templating engine in angular, which means that in templates
123+
* you can treat promises attached to a scope as if they were the resulting values.
124+
* - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains
125+
* all the important functionality needed for common async tasks.
11126
*/
12-
function qFactory(nextTick, exceptionHandler) {
127+
function $QProvider() {
13128

14-
nextTick = nextTick || function(callback) {
15-
setTimeout(callback, 0); // very rare since most of queueing will be handled within $apply
16-
};
129+
this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
130+
return qFactory(function(callback) {
131+
$rootScope.$evalAsync(callback);
132+
}, $exceptionHandler);
133+
}];
134+
}
17135

18-
exceptionHandler = exceptionHandler || function(e) {
19-
// TODO(i): console.error is somehow reset to function(a) {}, it might be a JSTD bug
20-
if (console && console.log) {
21-
console.log(e);
22-
}
23-
}
24136

137+
/**
138+
* Constructs a promise manager.
139+
*
140+
* @param {function(function)} nextTick Function for executing functions in the next turn.
141+
* @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
142+
* debugging purposes.
143+
* @returns {object} Promise manager.
144+
*/
145+
function qFactory(nextTick, exceptionHandler) {
25146

26147
/**
27148
* @ngdoc
@@ -264,110 +385,3 @@ function qFactory(nextTick, exceptionHandler) {
264385
all: all
265386
};
266387
}
267-
268-
/**
269-
* @ngdoc service
270-
* @name angular.module.ng.$q
271-
* @requires $rootScope
272-
*
273-
* @description
274-
* A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).
275-
*
276-
* [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
277-
* interface for interacting with an object that represents the result of an action that is
278-
* performed asynchronously, and may or may not be finished at any given point in time.
279-
*
280-
* When it comes to error handling, deferred and promise apis are to asynchronous programing what
281-
* `try`, `catch` and `throw` keywords are to synchronous programing.
282-
*
283-
* <pre>
284-
* function asyncGreet(name) {
285-
* var deferred = $q.defer();
286-
*
287-
* setTimeout(function() {
288-
* if (okToGreet(name)) {
289-
* deferred.resolve('Hello, ' + name + '!');
290-
* } else {
291-
* deferred.reject('Greeting ' + name + ' is not allowed.');
292-
* }
293-
* }, 1000);
294-
*
295-
* return deferred.promise;
296-
* }
297-
*
298-
* var promise = asyncGreet('Robin Hood');
299-
* promise.then(function(greeting) {
300-
* alert('Success: ' + greeting);
301-
* }, function(reason) {
302-
* alert('Failed: ' + reason);
303-
* );
304-
* </pre>
305-
*
306-
* At first it might not be obvious why this extra complexity is worth the trouble. The payoff
307-
* comes in the way of
308-
* [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).
309-
*
310-
* Additionally the promise api allows for composition that is very hard to do with the
311-
* traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
312-
* For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
313-
* section on serial or paralel joining of promises.
314-
*
315-
*
316-
* # The Deferred API
317-
*
318-
* A new instance of deferred is constructed by calling `$q.defer()`.
319-
*
320-
* The purpose of the deferred object is to expose the associated Promise instance as well as api's
321-
* that can be used for singnaling the successful or unsucessful completion of the task.
322-
*
323-
* **Methods**
324-
*
325-
* - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
326-
* constructed via `$q.reject`, the promise will be rejected instead.
327-
* - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
328-
* resolving it with a rejection constructed via `$q.reject`.
329-
*
330-
* **Properties**
331-
*
332-
* - promise – `{Promise}` – promise object associated with this deferred.
333-
*
334-
*
335-
* # The Promise API
336-
*
337-
* A new promise instance is created when a deferred instance is created and can be retrieved by
338-
* calling `deferred.promise`.
339-
*
340-
* The purpose of the promise object is to allow for interested parties to get access to the result
341-
* of the deferred task when it completes.
342-
*
343-
* **Methods**
344-
*
345-
* - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved
346-
* or rejected calls one of the success or error callbacks asynchronously as soon as the result
347-
* is available.
348-
*
349-
* This method *returns a new promise* which is resolved or rejected via the return value of the
350-
* `successCallback` or `errorCallback`.
351-
*
352-
*
353-
* # Differences betweeb Kris Kowal's Q and $q
354-
*
355-
* There are three main differences:
356-
*
357-
* - $q is integrated with the {@link angular.module.ng.$rootScope.Scope} Scope model observation
358-
* mechanism in angular, which means faster propagation of resolution or rejection into your
359-
* models and avoiding unnecessary browser redraws, which would result in flickering UI.
360-
* - $q promises are reconginized by the templating engine in angular, which means that in templates
361-
* you can treat promises attached to a scope as if they were the resulting values.
362-
* - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains
363-
* all the important functionality needed for common async tasks.
364-
*/
365-
// TODO(i): move elsewhere
366-
function $QProvider() {
367-
368-
this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
369-
return qFactory(function(callback) {
370-
$rootScope.$evalAsync(callback);
371-
}, $exceptionHandler);
372-
}];
373-
}

0 commit comments

Comments
 (0)