Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for completion after multiple promises in parallel using jQuery

I want to queue multiple asynchronous ajax requests using deferred/promise implementation of jquery:

function doSomething() {
    console.log('doSomething')};

function makeMultiAjaxRequests1() {
    console.log('makeMultiAjaxRequests1')};

function makeMultiAjaxRequests2() {
    console.log('makeMultiAjaxRequests2')};

var step1 = function () { 
    var promise = new $.Deferred().promise();   
    makeMultiAjaxRequests1(); 
    return promise; }

var step2 = function () {
    var promise = new $.Deferred().promise();
    makeMultiAjaxRequests2();
    return promise; } 

step1()
   .then(step2())
   .done(doSomething());

$.when(step1(), 
       step2())
   .done(function () {
    doSomething();
});

Here is the fiddle link. So my question is:

In the pattern where step1 and step2 are executed in parallel, the code does not reach the last handler function. Why?

like image 716
crishushu Avatar asked Dec 09 '13 19:12

crishushu


People also ask

What code pattern do you use when you want to wait for multiple promises to resolve before returning from a function?

Use of setTimeout() function: In order to wait for a promise to finish before returning the variable, the function can be set with setTimeout(), so that the function waits for a few milliseconds.

How would you wait for the results of more promises in JavaScript?

The keyword await is used to wait for a Promise. It can only be used inside an async function. This keyword makes JavaScript wait until that promise settles and returns its result.

How do you call multiple promises at once?

In this approach, we will use Promise. all() method which takes all promises in a single array as its input. As a result, this method executes all the promises in itself and returns a new single promise in which the values of all the other promises are combined together.

Does Promise all wait for all promises?

Using Promise.all()Promise.all waits for all fulfillments (or the first rejection).


2 Answers

You need to resolve the deferred obj in step1 and step2

Try this

function doSomething() {
    console.log('doSomething')};

function makeMultiAjaxRequests1(deferred) {
    console.log('makeMultiAjaxRequests1')
    deferred.resolve()};

function makeMultiAjaxRequests2(deferred) {
    console.log('makeMultiAjaxRequests2')
    deferred.resolve()};

var step1 = function () { 
    var deferred = new $.Deferred();   
    makeMultiAjaxRequests1(deferred); 
    return deferred; }

var step2 = function () {
    var deferred = new $.Deferred();
    makeMultiAjaxRequests2(deferred);
    return deferred; } 

step1().then(step2).done(doSomething);

$.when(step1(), step2()).done(function () {
    doSomething();
});
like image 120
Daiwei Avatar answered Sep 19 '22 22:09

Daiwei


@Daiwei gives a good answer.

A common gist to be referred to is https://gist.github.com/sergio-fry/3917217 by sergio-fry.

Should you want to have a more dynamic approach where you don't know beforehand how many arguments you are running parallel, here is a good example extension of JQuery (1.10+):

$.whenAll = function (deferreds) {
    function isPromise(fn) {
        return fn && typeof fn.then === 'function' &&
            String($.Deferred().then) === String(fn.then);
    }
    var d = $.Deferred(),
        keys = Object.keys(deferreds),
        args = keys.map(function (k) {
            return $.Deferred(function (d) {
                var fn = deferreds[k];

                (isPromise(fn) ? fn : $.Deferred(fn))
                    .done(d.resolve)
                    .fail(function (err) { d.reject(err, k); })
                ;
            });
        });

    $.when.apply(this, args)
        .done(function () {
            var resObj = {},
                resArgs = Array.prototype.slice.call(arguments);
            resArgs.forEach(function (v, i) { resObj[keys[i]] = v; });
            d.resolve(resObj);
        })
        .fail(d.reject);

    return d;
};

See the code in action with a dynamic live example:

http://jsbin.com/nuxuciwabu/edit?js,console

like image 25
mraxus Avatar answered Sep 18 '22 22:09

mraxus