2

So I'm playing around with promises and jQuery and I came up with the code below:

var timeoutAsync = function(millis) {
    var deferred = $.Deferred();
    setTimeout(function () { deferred.notify(millis); deferred.resolve(); }, millis);
    return deferred.promise();
};

$(document).ready(function() {
    var firstPromise = timeoutAsync(1000);
    var secondPromise = timeoutAsync(2000);
    var thirdPromise = timeoutAsync(3000);
    var fourthPromise = timeoutAsync(1234);
    $.when(firstPromise, secondPromise, thirdPromise, fourthPromise)
        .done(function() { alert("LOL"); })
        .fail(function() { alert("FAIL"); })
        .progress(function(msg) { console.log(msg); });
});

I'd expect my console to show me four values, namely: 1000, 1234, 2000 and 3000. And it did when I put a console.log statement in the setTimeout callback. But with the code above I get 1000 four times. I'm pretty sure I'm missing something here but I can't seem to find a hint in the docs as to why this would happen. So why does this happen?

I'm using jQuery 2.1.1 and I'm testing on firefox but it also happens in IE.

Vincent
  • 1,459
  • 15
  • 37

1 Answers1

1

It's because you're creating four different deferreds, and passing them all to $.when.
This creates a set of arguments for the progress handler

If you do it like this

.progress(function(msg1, msg2, msg3, msg4) { 
     console.log(msg1, msg2, msg3, msg4); 
});

You'll see the arguments as the deferreds are resolved

FIDDLE

In other words, you're logging only the first argument, which is the value passed to the first deferred, every time.

When checking progress you have to use one deferred object, and then use the notify and progress methods on that deferred, you shouldn't create four different deferreds.

Something like

var timeoutAsync = function(deferred, millis) {
    setTimeout(function () { 
        deferred.notify(millis); 
    }, millis);
};

$(document).ready(function() {
    var deferred = $.Deferred();

    var firstPromise = timeoutAsync(deferred, 1000);
    var secondPromise = timeoutAsync(deferred, 2000);
    var thirdPromise = timeoutAsync(deferred, 3000);
    var fourthPromise = timeoutAsync(deferred, 1234);

    deferred.done(function() { alert("LOL"); })
            .fail(function() { alert("FAIL"); })
            .progress(function(msg) { 
                console.log(msg); 
            });
});

FIDDLE

adeneo
  • 312,895
  • 29
  • 395
  • 388
  • Thank you very much for your answer. After reading your answer I read up on the docs for progress() and it does (in a way ..) say what you're saying. But definitly not as clear as you've explained it. – Vincent Oct 26 '14 at 14:12