398 CHAPTER 9 Asynchronous operations
“always!” message before the “done!” or “failed!” message because the always subscription is
before the others. If the always subscription is the last subscription, it will execute last.
Subscribing to a completed promise object
It’s useful to know that you can subscribe to the promise object even after it’s been resolved.
This immediately executes the function you pass to the done method. Consider the following
example in which two promise objects are used to chain actions together, and the completion
of secondPromise adds a function to firstPromise, which has already completed.
function abcAsync() {
var firstPromise = timeoutAsync(2000);
firstPromise.done(function () {
var secondPromise = timeoutAsync(3000);
secondPromise.done(function () {
firstPromise.done(function () { alert('done!') });
});
});
return firstPromise;
}
In this example, after 2 seconds, the firstPromise object completes, which starts a new
timeout, thus creating the secondPromise object. After 3 seconds (5 seconds from the start of
the function), the secondPromise object completes, which adds a function to the firstPromise
object. Because the firstPromise object has already completed, the function is executed
immediately. Existing subscriptions are not re-executed because the subscriber functions are
guaranteed to execute only once.
Chaining promises by using the pipe method
There is a problem with the previous code example in that abcAsync is returning the first-
Promise object. That is a problem because the abcAsync object should return a promise
object that indicates the completion of all code within the function. In this case, when first-
Promise is complete, code is still executing that’s represented by the secondPromise object.
It would be conceptually correct to try to return the secondPromise object, but the second-
Promise object isn’t even created for 2 seconds.
Did you also notice that chaining the second asynchronous operation required you to nest
the second operation inside the successful completion code of the first asynchronous opera-
tion? When you need to chain three, four, or more operations, you can get caught up in nest-
ing several levels and creating unmanageable code, as the following example demonstrates.
function abcAsync() {
var firstPromise = timeoutAsync(2000);
firstPromise.done(function () {
var secondPromise = timeoutAsync(3000);
secondPromise.done(function () {
var thirdPromise = timeoutAsync(1000);