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);
    }
);