0

I'm having trouble getting a queue of deferred objects to call back when complete.

As you can see in the following code, I'm creating a queue (as per this answer: JQuery - $.when syntax for array of Deferred objects) but the answer unfortunately doesn't include the content of the doSomeWork function. Presumably I need to call defer.resolve() as I am doing below.

    _getTagLabels: function(tags, callback){
        var self = this;           

        var queue = [];

        for (i = 0; i < tags.length; i++) {
            var tag = tags[i];

            queue.push(new $.Deferred(

                    function (defer){
                        self.getLabel(tag.id, function(label) {
                            tag.label = label;
                            defer.resolve();
                        })
                    }

                ).promise()
            );
        }

        $.when.apply(undefined, queue).then(function(){
            callback();
        });            
    }

However, the callback is never reached. Even though breakpoints on the defer.resolve() are being hit and the tag label being set. I've tried the various other methods of defer, such as done() and then() but none seem to trigger the callback.

EDIT

Here's getLabel and getConcept:

getLabel: function(id, callback) {
    var self = this;

    self.getConcept(id, function(concept){
        callback(concept.label);
    });
}

getConcept: function(id, callback){
    var self = this;

    // abort any current queries.
    if (self.getConceptXHR) self.getConceptXHR.abort();

    var url = String.format(self.options.conceptTemplate, self.options.serviceEndpointUrl, id);

    self.getConceptXHR = $.ajax({
        dataType: "jsonp",
        url: url,
        success: function (response) {
            callback(response);
        }
    });
}
Community
  • 1
  • 1

1 Answers1

0
var obj = {
    _getTagLabels: function(tags, callback){
        var self  = this,
            queue = [];

        for (i = 0; i < tags.length; i++) {
            (function(y)
                queue.push(
                    self.getLabel(tag.id).done(function(result) {
                           tags[y].label = result.label;
                    });
                );
             })(i);
        }

        $.when.apply($, queue).done(callback);
    },
    getLabel: function(id){
        if (this.getConceptXHR) this.getConceptXHR.abort();
        var url = String.format(this.options.conceptTemplate, this.options.serviceEndpointUrl, id);

        this.getConceptXHR = $.ajax({
            dataType: "jsonp",
            url: url
        });
        return this.getConceptXHR;
    }
}
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • I had to alter the syntax of that a bit for it to run, but the callbacks still aren't getting called. Not sure why you're wrapping the queue.push in a self-executing anonymous function? If I put that function inside the queue.push it's executed after the callbacks are fired... – user2365778 May 09 '13 at 12:06
  • The point was to use the built in deferred in $.ajax by returning it, instead of creating new deferred's and using a callback function. The extra function is a closure to keep the value of i, as the getLabel() function is async. The only problem I see, is aborting any ongoing ajax calls, as that sort of defeats the purpose of doing multiple calls and storing them in an array, as only the last ajax call in the loop will be completed, the others will be aborted on each subsequent iteration. – adeneo May 09 '13 at 13:56
  • I ended up using another ajax service to return all the labels at once. Thank you for your help. – user2365778 May 09 '13 at 14:02