panthro
panthro

Reputation: 24061

Using deferred and when

I make an ajax call in a loop, the ajax call is in the class self.fileUpload:

$.when.apply($, $.map($('.file-new'), function(fileNewTemplate, i) {

        var formData = new FormData();

        return self.fileUpload.upload(formData).then(function(data){
            return $.Deferred().resolveWith(this);

        }).fail(function(){
            console.log('ajax call failed');

        });

    })).done(function(){
        console.log('when done');

    })
    .always(function(){
        console.log('when always');
    })
    .fail(function(){
        console.log('when fail');
    })

The problem is, when one ajax call fails, the fail of the when is called. I need a solution that would call done or always once all promises are returned, despite whether some or all failed.

I checked out the answers here:

$.Deferred: How to detect when every promise has been executed

And as you can see from the above code, I have implemented the accepted solution.

The problem is, done is still never called and always is called as soon as one ajax call fails.

Where am I going wrong?

Upvotes: 0

Views: 48

Answers (1)

zerkms
zerkms

Reputation: 254886

Where am I going wrong?

It's not you, but how $.when() works.

But you can easily implement a function that would resolve after all promises either resolve or reject:

var waitAllRegardlessResult = function(promises) {
    var cnt = promises.length,
        d = $.Deferred(),
        countHandler = function() {
            if (--cnt == 0) {
                d.resolve();
            }
        };

    promises.map(function(promise) {
        promise.always(countHandler);
    });

    return d.promise();
};

Demo: http://jsfiddle.net/X38JT/

So this function will return a promise object that is resolved after all promises passed as an array either resolved or rejected

Upvotes: 1

Related Questions