Last Updated: February 25, 2016
·
8.539K
· zachcase

Using Multiple Deferred Promises - JavaScript/jQuery

This tip is not to go into great detail about how or when you should use Deferred promises, the purpose is to provide people with the knowledge of how to use multiple deferred statements and have .done() run once all the defers are resolved.


Our Problem

We have three functions, one is to query our partners, the other is to query our users, and the last is to process the information found from the queries.


Out Code

Right now, our function to run these looks like:

function getInfo(){
    /* Query Partners */
    queryPartners();
    /* Query Users */
    queryUsers();
    /* Process Info from Users */
    processInfo();
}

The problem here is that since all of these functions are asynchronous, and the queries will not process quick enough before processInfo() runs, we will get an error along the lines of the info not being present to process. That's where the deferred promises come in, we need to tell the function to not run processInfo() until both queries are finished.

So our three functions inside getInfo() look like this right now.

function queryPartners(){
    /* Query Partners */
    ... // The code for however we are querying and returning the data.
}
function queryUsers(){
    /* Query Users*/
    ... // The code for however we are querying and returning the data.
}
function processInfo(){
    /* Process Data */
    ... // The code for however we are processing the info.
}

The Solution

Let's change the functions to accept a parameter of promise, and when all of the code is complete in each function we'll .resolve() the promise and return it back.

function queryPartners(promise){
    /* Query Partners */
    ... // The code for however we are querying and returning the data.

    /* Query is complete, resolve promise */
    promise.resolve();
    return promise;
}
function queryUsers(promise){
    /* Query Users*/
    ... // The code for however we are querying and returning the data.

    /* Query is complete, resolve promise */
    promise.resolve();
    return promise;
}
function processInfo(promise){
    /* Process Data */
    ... // The code for however we are processing the info.

    /* Processing is complete, resolve promise */
    promise.resolve();
    return promise;
}

Now let's go back to the getInfo() function and change it so that it supplies the functions with their deferred promise and that it waits for the queries to finish before running processInfo().

function getInfo(){
    /* Initialize Deferred Promises for each function */
    var a = $.Deferred();
    var b = $.Deferred();
    var c = $.Deferred();

    /* Query Partners, supply the promise (a) */
    a = queryPartners(a);
    /* Query Users, supply the promise (b) */
    b = queryUsers(b);

    /* .when() both queries are .done(), run processInfo() */
    $.when(a,b).done(function(){
        /* Process Info from Users, supply promise */
        c = processInfo(c);
    });

    return c;
}

What that last little bit inside the $.when().done() allows, is when you call getInfo() you can also follow it with .done() if you need to wait to progress your code follow until getInfo() is complete as well.

Have questions, comments? Leave them below and I'll answer to the best I can!

Cheers!