Nathan Ziarek
Nathan Ziarek

Reputation: 11

Re-associate AJAX call with original URL using jQuery

I'm not sure how to even explain this, which makes it very difficult to search on (especially because I am SURE this is an error in thinking).

I have an array of objects:

var a = [
    {
        url: "http://www.discusionboard.com/list-of-boards/", 
        name: "Discussion Board One", 
        threads: []
    },
    {url: "...", name: "...", threads: [] }
]

I am looping through these objects, downloading each page, and then trying to add the threads back to the original object.

for( var i = 0; i < a.length; i++ ) {
    jQuery.get(a[i].url, function(result, status, xhr) {
        /* result is list of threads separated by "[SPLIT]" */
        a[i].threads = result.split("[SPLIT]")
    });
}

My issue, then, is that the "i" in a[i].threads is undefined. I can't find a way to pass it into the function, and that makes me think I'm just fundamentally misunderstanding a core concept here.

Any help would be GREATLY appreciated. I'm happy to read myself, if someone could just give me an idea of what I should look for. As you can see by my title, I'm having a hard time even describing what I'm trying to do.

Upvotes: 1

Views: 301

Answers (1)

PleaseStand
PleaseStand

Reputation: 32052

This is a good example of the closure loop problem. The callback function you pass to jQuery is executed only after the loop has finished (even after the function it is inside of returns a value). Therefore, a[i] (to the callback function) will always be the last element of the array. jQuery.ajax provides the context setting to address this problem:

for( var i = 0; i < a.length; i++ ) {
    jQuery.ajax({
        url: a[i].url,
        context: a[i],
        success: function(result, status, xhr) {
            /* result is list of threads separated by "[SPLIT]" */
            this.threads = result.split("[SPLIT]")
        }
    });
}

Note that if you have code afterward that needs to make use of the completed objects, that is also a problem. To address this, you would need to put this outside the callback function:

var numRequests = a.length;

And this at the end of the callback function:

if(!--numRequests) {
    // Do whatever now that all object data has been loaded.
}

Upvotes: 1

Related Questions