0

I know how to execute multiple ajax calls at once using $.when. E.g.:

$.when( d1, d2 ).done(function ( v1, v2 ) {
    console.log( v1 ); // "Fish"
    console.log( v2 ); // "Pizza"
})

However, I want to use this in a method so that I can use it multiple times to return a value (e.g.

function getDataFor(list) {
    var data = [];

    $.when(d1(list), d2(list)).done(function (v1, v2) {
        console.log(v1);
        console.log(v2);

        data = [v1, v2];
    });

    return data;
}

What is the proper format for this? Also, is it essentially useless to use .then over .done in the above example unless I plan on having another promise follow that one?

edit: I do not feel that this is a duplicate question. Although I understand why it seems like that, I was really just looking to know if there was an out-of-the-box or library-based (e.g., jquery/bluebird) wrapper like .NET's WaitAll method which takes a set of asynchronous calls and blocks the thread until they are all completed. I've accepted that this isn't possible, but I don't feel it is a duplicate.

Dinerdo
  • 560
  • 7
  • 27
  • your code above will never work because `return data;` will always run before the ajax calls complete, and therefore `data` won't be populated. Anything you want to happen after the ajax calls complete, and which relies on data that they return, _must_ be triggered via either the "done" or "then" callbacks. What you _could_ do, is have your getDataFor method return the Promise which is returned by $.when, so that outside code can attach its own .then / .done callbacks to that. You can have as many of those callbacks as you like attached to a promise. – ADyson Oct 10 '17 at 18:49
  • I know it won't work. I'm asking how to perform something with the intended effect of that example. I want that block to essentially act as one which has async: false as a property. There are a lot of arrays that don't change after initialization at the top of this legacy code, and they're all calling synchronous methods currently. There are too many dependencies as-is for me to try to chain 15 of them together in the given timeline, so I was just trying to at least get rid of a few of them by merging them together. I could do away with this by just setting them as global variables, but.. :( – Dinerdo Oct 10 '17 at 19:04
  • even if you set them global, if you try to use them before they're ready you'll have a problem. And it's impossible to know whether they're ready except within the callback. If you're currently relying on synchronous-ness to make things work, then some refactoring is inevitable unfortunately. Returning the promise is probably the best approach I can think of, then at least your calling code has got something to grab onto, and it can add its own .then callback to execute when everything has finished. – ADyson Oct 10 '17 at 19:25
  • I know some refactoring is needed.. That's what I'm doing. I'm not trying to apply 0 effort. I know what we have time for so I just wanted to see if anything like this was possible. It's not. That's fine. – Dinerdo Oct 10 '17 at 23:28
  • You can't use async calls and wrap them to make them synchronous. Just can't be done. Your `getDataFor()` function has to use async methods to return its result (either a callback or promise). The answer yours has been marked a duplicate of shows you ALL the various possibilities. – jfriend00 Oct 10 '17 at 23:31
  • Just do return `$.when(...)` and return the promise you already have. The caller of your function, then uses `getDataFor(...).then(...)`. – jfriend00 Oct 10 '17 at 23:37
  • I thought of that. That's not what I was asking so I don't feel that this is a duplicate question. – Dinerdo Oct 11 '17 at 04:49

1 Answers1

1

No, it's not possible for a function to return multiple times, and it's not possible to return any result variables before the ajax requests succeeded. You can however simply return a promise for the array of results - but for that you need to use then instead of done so that you can return from the callback. (Protip: just never use done or fail).

function getDataFor(list) {
    return $.when(d1(list), d2(list)).then(function (v1, v2) {
//  ^^^^^^                            ^^^^
        console.log(v1);
        console.log(v2);

        var data = [v1, v2];
        return data;
//      ^^^^^^
    });
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I'm not sure what you're talking about with returning multiple times. I just wanted to wait for several tasks to be completed before returning once like .Net's WaitAll method. I could do that with some messy timeouts, but I figured this was worth a shot. Thanks for the info about `then` btw! – Dinerdo Oct 10 '17 at 23:35
  • @Dinerdo Maybe I just misunderstood the "*I can use it multiple times to return a value*" part of your question – Bergi Oct 11 '17 at 00:04
  • Ah. I just wanted to use this method multiple times to return a value unique to each call (based on the list parameter). Poor wording on my behalf. – Dinerdo Oct 11 '17 at 04:45