Question

I'm trying to understand Javascript deferred functions. I have come up with an issue in a mobile application I'm developing with JQuery Mobile.

I have made a JSFiddle with the example but I paste here the code for clarity.

var promises = [];

function out() {
    var args = Array.prototype.slice.call(arguments, 0);
    document.getElementById('output').innerHTML += args.join(" ") + "\n";
}

function testDeferred(a) {
    return $.Deferred(function (d) {
        if (a == 1) {
            d.resolve(a);
        } else {
            d.reject(a);
        }
    });
}

function testDeferred2(a) {
    var deferred = new $.Deferred();

    if (a == 1) {
        deferred.resolve(a);
    } else {
        deferred.reject(a);
    }
    return deferred.promise();
}


promises.push(testDeferred(1));
promises.push(testDeferred2(1));

out(promises[0].state());
out(promises[1].state());

$.when.apply($, promises)
    .done(function () {
    out("Done");
});

What I intend:

  1. Push both testDeferred and testDeferred2 promises into the array "promises", forcing them to resolve.
  2. Execute both using $.when.apply.

What I achieve is both functions being executed at the very moment I push them. The prove is their state after pushing them becomes "resolved".

I removed the ".promise()" ending in testDeferred on purpose to test if I should return a promise or just the deferred. Same thing happened.

Please, I need some help here... Thanks in advance.

Was it helpful?

Solution

both functions being executed at the very moment I push them

Yes, that's what you are doing here:

promises.push(testDeferred(1));
promises.push(testDeferred2(1));

You are calling the functions, which will return resolved promises (or deferreds, for that matter). However, you will need to distinguish between executing the function, and resolving the promises.

Your code does that synchronously, which is rather unusual, normally you'd expect to execute the functions immediately and resolve the returned promise later:
When writing asynchronous code (imagine a setTimeout or a $.ajax in the test functions), then you are calling them immediately, which starts the asynchronous tasks right away, but get pending promise for their results.

function testDeferredDelay(a, ms) {
    var deferred = new $.Deferred();
    setTimeout(function() { // happens now
        deferred.resolve(a); // happens later
    }, ms);
    return deferred.promise(); // happens now
}

promises.push(testDeferredDelay(1, 50));
promises.push(testDeferredDelay(2, 100));

out(promises[0].state()); // pending
out(promises[1].state()); // pending

$.when.apply($, promises) // happens now
.done(function () {
    out("Done"); // happens later
});

(updated demo fiddle)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top