funny Q

funny Q

$q

$q can be used in two fashions — one which is more similar to Kris Kowal’s Q or jQuery’s Deferred implementations, and the other which resembles ES6 promises to some degree.

ES6 style

The streamlined ES6 style promise is essentially just using $q as a constructor which takes a resolver function as the first argument.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// assume that $q and $resource are available.
function = asyncGo() {
return $q( function(resolve, reject) {
$resource("www.example.com", {}, {})
.get({}, function(result) {
resolve("hello, " + result);
}, function(error) {
reject("sorry, " + error + " is not allowed");
})
});
};

var promise = asyncGo();
promise.then(function(greeting){
console.log(greeting);
}, function(err){
console.log(err);
});

Deferred style

The purpose of the deferred object is to expose the associated Promise instance as well as APIs that can be used for signaling the successful or unsuccessful completion, as well as the status of the task.

  • resolve(value) – resolves the derived promise with the value. If the value is a rejection constructed via $q.reject, the promise will be rejected instead.

  • reject(reason) – rejects the derived promise with the reason. This is equivalent to resolving it with a rejection constructed via $q.reject.

  • notify(value) - provides updates on the status of the promise’s execution. This may be called multiple times before the promise is either resolved or rejected.

1
2
3
4
5
6
promiseB = promiseA.then(function(result) {
return result + 1;
});

// promiseB will be resolved immediately after promiseA is resolved and its value
// will be the result of promiseA incremented by 1

$q vs. $rootScope

$q is integrated with the $rootScope.Scope Scope model observation mechanism in angular

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
it('should simulate promise', inject(function($q, $rootScope) {
var deferred = $q.defer();
var promise = deferred.promise;
var resolvedValue;

promise.then(function(value) { resolvedValue = value; });
expect(resolvedValue).toBeUndefined();

// Simulate resolving of promise
deferred.resolve(123);
// Note that the 'then' function does not get called synchronously.
// This is because we want the promise API to always be async, whether or not
// it got called synchronously or asynchronously.
expect(resolvedValue).toBeUndefined();

// Propagate promise resolution to 'then' functions using $apply().
$rootScope.$apply();
expect(resolvedValue).toEqual(123);
}));

then

then that can accept three arguments(three callback types)–success, failure, progress.
for defer object, resolve will apply to success, reject apply to failure and notify apply to progress.

a defer object contains always, done, fail methods! so the always and done will trigger if resovle be called and return a promise object, which contains resolved result.