Promises and deferred objects were introduced into ECMA to support asynchronous function handling
We'll cover the implementation of promises and deferred objects in Angular and jQuery below
ES6 Promises
A promise is an object to be used when asynchronous callbacks, variable assignments, or computation is required
A promise is used when some required value is not known or available at the time the relevant code is initially invoked
A promise is used when some required value is supplied asynchronously or lazily
ES6 Example
Here we create a promise object with callback
new Promise(), resolve(), and .then() constitute the core functions to be used
new Promise() creates a promise through a constructor
resolve() specifies the fulfillment of the promise - i.e. what it is that we're waiting for
reject() specifies that the promise has failed to resolve or that the promise is rejected
var promise = new Promise(
window.setTimeout(
function(resolve, reject) {
var exampleVar = "EXAMPLE VALUE";
resolve(exampleVar);
}, 5000)
);
.then() specifies what to do once the promise is fulfilled/resolved or unfulfilled/unresolved
val specifies the resolved value accessed through a callback
Here we wait for val to be made available pending the delayed execution of the above code
promise.then(
function(val) {
alert(val);
}
);
Angular $q
The implementation of promises and deferred objects in Angular revolves around the $q constructor
$q Promises
$q can be used to create a promise
var asyncExample = function() {
$q(function(resolve, reject) {
setTimeout(
function(resolve, reject) {
var exampleVar = "EXAMPLE VALUE";
resolve(exampleVar);
}, 5000);
});
};
.then() can be used in the same way
asyncExample.then(
function(val) {
alert(val);
}
);
$q Deferred
The Deferred API exposes $q as well as various signaling functionalities notifying of successful or unsuccessful resolution of code or tasks
Here we pass $q in as dependency available to a service
function exampleService($q) {
return {
getSomething() {
var defer = $q.defer();
setTimeout(
function() {
var exampleVar = "EXAMPLE VALUE";
defer.resolve(exampleVar);
}, 5000);
return defer.promise;
}
};
};
$q.defer(), .resolve(), and .promise specify creating a deferred instance, the resolution of the promise, and the exposed promise itself
Important Miscellany
$q.all() accepts an array of promises - .then() is invoked once all promises have resolved
var
promiseOne = $http.get('/api/todos'),
promiseTwo = $http.get('/api/comments');
$q.all([promiseOne, promiseTwo]).then(data => {
alert('All promises have resolved!');
});
$q.when() is identical to $q.resolve()
jQuery $.Deferred
jQuery makes use of $.Deferred() to support asynchronous computation handling
Again, we find the familiar trifecta - $.Deferred() which creates the deferred instance, .resolve() which specifies the resolution of the promise, and .promise() which exposes the promise object
var asyncExample = function() {
var deferred = $.Deferred();
setTimeout(
function() {
var exampleVar = "EXAMPLE VALUE";
deferred.resolve(exampleVar);
}, 5000);
return deferred.promise();
};
Once fulfilled the above code is handled similarly
asyncExample().then(
function(val) {
alert(val);
}
);
Alternative Handling
We can also wrap the asynchronous function asyncExample() using $.when() which provides greater functionality and flexibility
For example, $.when() provides multi-promise support and the ability to pass in functions that do not return a promise
Unfortunately, the example above gains little advantage from $.when() as it accomplishes exactly the same thing
$.when(asyncExample()).then(
function(val) {
alert(val);
}
);
Here, however, we accomplish multi-promise resolution using $.when() which is not supported through $.Deferred() alone
$.when(asyncExampleOne(), asyncExampleTwo()).then(
function(valOne, valTwo) {
alert(valOne);
alert(valTwo);
}
);