8

I'm working on a web application and I need to load a few files $.ajax. I found something interesting in $.when().then().

It works great when I don't have anything special to do with the data returned by the request like this example:

$.when(
    $.getScript('js/script1.js'),
    $.getScript('js/script2.js')
).then(function(){
    // Do whatever I want once both scripts are loaded...
});

If works well when I have a single ajax request like this:

$.when(
    $.ajax('xml/myxml.xml')
).then(function(data){
    // Here I can work with data like I would with a regular ajax request
    alert($(data).find('mynode').text());
})

But if I try the following, I can't get it to work:

$.when(
    $.ajax('xml/myxml.xml'),
    $.getScript('js/script.js')
).then(function(data){
    // But here, I can't access $(data).find('mynode')...
})

I read the deferred object page but most of it was too technical for me and I'm unable to understand how I am supposed to be able to get my ajax data when I'm using $.when().then() to load scripts and data from multiple sources.

So if someone can help me find out how to use my ajax data in my test case above, it would be great! And if in the meantime someone can explain the deferred object thing in a manner that is easier to understand than the official jQuery documentation, it would be awesome!

Thank you!

Gabriel
  • 2,720
  • 4
  • 28
  • 36
  • Try inspecting the arguments returned by `deferred.then` in that case. `console.log(arguments)` please post results. – Kevin B Jan 19 '12 at 20:06
  • Look at the example on this page: http://api.jquery.com/jQuery.when/ – Ben Lee Jan 19 '12 at 20:11
  • Your `then` method should accept two arguments: `.then(function(a1, a2) {`.... `a1` will be the results of the first ajax call. `a2` will be the results of the getscript call. – Ben Lee Jan 19 '12 at 20:12
  • @Ben Lee - It doesn't have to. Essentially, if you don't include a second argument, it is the same as using `.done()`. – Kevin B Jan 19 '12 at 20:14
  • @Kevin B: The result of console.log(arguments) is too long to post here... But it's an array and if I understand correctly what I see, it looks like I have an array that has the same length as my $.ajax count. So I should be able to get my xml data from there... – Gabriel Jan 19 '12 at 20:28

1 Answers1

3

Apparently, for each deferred object, at least if it is an Ajax request, $.when passes an argument like [ "success", statusText, jqXHR ] to the callback. jqXHR is an object representing the XMLHttpRequest (more about it in the $.ajax documentation). So the following should work:

$.when(
    $.ajax('xml/myxml.xml'),
    $.getScript('js/script.js')
).then(function(a){
    $(a[2].responseText).find('mynode');
});

See the first example in the $.when documentation.

Regarding deferred objects in general, maybe this question helps.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Does `.done()` work the same way, since you probably already have a demo up to test it? Considering that since you aren't also applying fail callbacks, it makes more sense to use `.done` rather than `.then`? – Kevin B Jan 19 '12 at 20:15
  • @KevinB: I have not tested it yet to be honest. Done would work the same way and you are right, it might be better to add different success and error handlers. Though I don't know how the argument looks in a failure case. Probably `["error", statusText, jqXHR ]`, but I don't know for sure (and have the time to test it right now). – Felix Kling Jan 19 '12 at 20:19
  • Thanks Felix, your answer put me on the right track but the index of the xml data is 0, not 2... Si if I do $(data[0]).find('mynode') it works... – Gabriel Jan 19 '12 at 20:36
  • @FelixKling: Can you change your answer with a[0] instead of a[2]? At the moment, your code is not working but with that change it'll work so I'll select it as the appropriate answer for anyone who comes here in the future... Thanks! :) – Gabriel Jan 20 '12 at 18:46
  • Since $.when is looking to promises, the part of the docs you need to look at is: `jqXHR.then(function(data, textStatus, jqXHR) {}, function(jqXHR, textStatus, errorThrown) {});` So if all your ajax calls succeed, you'll get an array of arrays each of which has 'data' as the first item. If any of the ajax calls fail, your current code just won't be called. You'd add a second func to 'then' to handle the fail case with 'errorThrown' last. Note that you'll always just get the first failure back (you'd need to wrap the ajax calls to get back all failures). – ShawnFumo Nov 24 '13 at 22:27