1

I'm having a hard time wrapping my head around JQuery promises and deferred objects so please bear with me. I should also say my application is using React, Typescript, and ES6.

Let's say I have an array of objects:

[{ Object }, { Object}, { Object }]

What I'm trying to do is, for each object in the array, make a call out to an API with a different parameter from the object, get the response, and then make another call to the same API for the remaining objects. Basically, I want to chain these calls together so I make one at a time and then add them into my application state.

Here's what I've got so far but it's, obviously, not working:

private getData(options: any[]): void {
    let promises: any[] = [];

    options.map((option: any, key: number) => {
        let deferred: JQueryDeferred<any> = $.Deferred();
        deferred.done((response) => {
            return this.getIndividual(option)
                .done(response => {
                    console.log('done', response);
                });
        });

        promises.push(deferred);
    });

    $.when.apply($, promises)
        .then((response) => {
            console.log('response', response);
        }).fail((error) => {
            console.log("Ajax failed");
        })
        .done(() => {
            console.log('done');
        });
}

private getIndividual(option: any) {
    return apiCall(option.hashKey);
}
addam
  • 757
  • 1
  • 6
  • 11
  • Did you read [this canonical QA](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) ? – Denys Séguret Feb 24 '17 at 08:31
  • using `options.map` and effectively discarding the result is pointless – Jaromanda X Feb 24 '17 at 08:41
  • Possible duplicate of [Resolve promises one after another (i.e. in sequence)?](http://stackoverflow.com/questions/24586110/resolve-promises-one-after-another-i-e-in-sequence) – Andreas Feb 24 '17 at 08:44
  • I hadn't seen that before so thank you. I understand that this isn't optimal to be reliant on synchronous calls. However, how this application was architected, it requires multiple calls out to load data from other services when the component loads. Since I don't want to overload the server with calls, I think this is the best solution. – addam Feb 24 '17 at 08:44
  • Do you want to make the calls to the API in a queue? Or you just want to make a call for each object in your array? – codtex Feb 24 '17 at 08:44
  • I guess the answer would be both. If I could create a queue that would container a call for each item in the array, that would be optimal. – addam Feb 24 '17 at 08:54

1 Answers1

2

If your calls aren't dependent on each other and you just need to act on them once all the promises are complete, use Promise.all:

var xhr1 = doXhrPromise(1);
var xhr2 = doXhrPromise(2);
var xhr3 = doXhrPromise(3);
var xhr4 = doXhrPromise(4);

Promise.all([xhr1, xhr2, xhr3, xhr4]).then(() => {
  // do something once all the promises resolve
});

If you need to do the calls in sequence because the next call relies on data from the previous call, then just chain them together like so:

doXhrPromise(1)
.then((data) => { return doXhrPromise(data.nextId); })
.then((data) => { return doXhrPromise(data.nextId); })
.then((data) => { return doXhrPromise(data.nextId); })
.then((data) => { return doXhrPromise(data.nextId); })
Daniel T.
  • 37,212
  • 36
  • 139
  • 206