简体   繁体   中英

How do I synchronise API responses in JavaScript?

In JavaScript, have a need to retrieve data from two API calls and use both to process data for the display.

For example; one call returns tasks with a user id, the other returns a list of user id's and names. Before I display onscreen I want to process the user ids so that the user name is shown against the task data.

(The best I can think of is a flag for each response (set to true when done)which is checked by the other call(s). So that only the last call would proceed to build the page).

This is a bit of a stub since it doesn't handle failures, but provides a basic flow. Since you don't know which will return first, fire them both off and do something when both have delivered data.

And this assumes that you have some sort of callback that you can customize to call when your api completes a request.

var apiData = {
  data1: null,
  data2: null
};

function callApis() {
  API.call1({ onComplete: function(result) {
    apiData.data1 = result;
    completeApiRequest();
  }});

  API.call2({ onComplete: function(result) {
    apiData.data2 = result;
    completeApiRequest();
  }});
}

function completeApiRequest() {
  if (apiData.data1 && apiData.data2) {
    doStuff();
  }
}

callApis();

If you're using an AJAX call, I'd put the (second) call that depends on the first set of data, into the callback handler of the first call:

Using jQuery:

jQuery.ajax({
   url: url, /* first call */
   data: myData,
   cache: false,
   success: function(data) {
               /* ... processing code ... */
               jQuery.ajax({
                  url: url, /* second call */
                  data: someMoreData,
                  cache: false,
                  success: function(data) {
                           /* ... processing code ... */
                           }
               });
            }
});

Here's another solution that does it in parallel:

var requestOneCompleted = false;
var requestTwoCompleted = false;

jQuery.ajax({
   url: url, /* first call */
   data: myData,
   cache: false,
   success: function(data) {
               /* ... processing code ... */
               requestOneCompleted = true;
            }
});

jQuery.ajax({
   url: url, /* second call */
   data: someMoreData,
   cache: false,
   success: function(data) {
               /* ... processing code ... */
               requestTwoCompleted = true;
            }
});

setInterval(function() {
   if(requestOneCompleted && requestTwoCompleted) {
      doStuffWithData();
   }
}, 250);

Note I haven't tested this.

I think flags are probably your best. Or, you could do synchronous AJAX calls (then it'd be SJAX of course!) if you want to enforce a sequence of requests. Of course, this will block the remainder of your script from executing until first one and then the second have finished.

I think you're pretty much there already. Maybe use a tiny state machine with three states, noResponse, oneResponse and bothResponses (implied), something along the lines of:

var state = "noResponse";
callOne.onresponse = callTwo.onresponse = function() {
  switch(state) {
  case "noResponse":
    state = "oneResponse";
    break;
  case "oneResponse":
    processBothResponses();
    break;
  }
}

I assume that all the data you need is in your two call objects, and you can examine them and do your cross checking in processBothResponses().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM