satya
satya

Reputation: 59

How to two async calls Synchronously in javascript?

I have a common generic function which will make use for ajax calls. While triggering the first time I will get the whole data from the server and I will maintain local scope. So In in the second time, it won't the server for the data. In my case the problem is the first request is async request while processing the first request second request is coming and again it is hitting the server. Now, how I can put the second request in waiting for state until the first request was finished?

a.js will call the call.js which has the ajax call: get();

b.js also will call the same function. In the second the data was available in global variable so that it won't make any ajax call: get();

call.js:

var get = function() {
  var global = [];
    if (Object.keys(global).length)
      retrun global;
    ajaxcall({
      // ...
    }).done(function(data) {
      global = data;
    }).fail(function(err) {
    });
  }

In this case while processing the first request second request is coming. So it is making another call.

Upvotes: 0

Views: 700

Answers (5)

Alex
Alex

Reputation: 18526

To have just one request running to the server, and the next request has to wait until the first one is done

The question needs a couple more lines of code and has been answered before, so I will just link to a couple of examples. What you should be looking for are the keywords "ajax queue".

Queue AJAX calls

Sequencing ajax requests

I would recommend using one of the available libraries for this case, but the first answer also gives an example of some library-free code.

To have just one request and cache the result

Usually the first thing to do would be to just keep track of your existing call.

var isCallInProgress = false;
var global = [];
var get = function() {
if (Object.keys(global).length)
  return global;

if (isCallInProgress)
  return;        

isCallInProgress = true;
ajaxcall({
  // ...
}).done(function(data) {
  global = data;
  isCallInProgress = false;
}).fail(function(err) {
});
}

Depending on your usecase, you may need to do some further work here. Returning the data immediately if its already loaded and returning nothing if its not is not really ideal. Something like this would be more along the usual expected API design:

var isCallInProgress = false;
var global = [];
var get = function(returnCallback) {
 if (Object.keys(global).length){
   // callback immediately
   // you might also want to wrap this in a promise or setTimeout, depending on your expected behavior
   returnCallback(global);
 } 

 if (isCallInProgress)
   return;         

 isCallInProgress = true;
 ajaxcall({
   // ...
 }).done(function(data) {
   global = data;
   isCallInProgress = false;

   // async callback
   returnCallback(global);

 }).fail(function(err) {
     // error callback would probably also be appreciated by the caller
 });
}

Upvotes: 2

RedDwarfian
RedDwarfian

Reputation: 708

The $.ajax function, in jQuery, returns a jQuery XMLHttpRequest object, or jqXHR. That object can be stored, and functions can be run on it.

The best option would be to store the returned jqXHR or XMLHttpRequest in a globally accessible variable. In each of the two functions, check to see if that globally accessible variable is null. If it is, then run it. Once the ajaxcall has completed, clear the varname:

varname = ajaxcall({
    // ...
})
// ...
.always(function(){
    varname = null;
);

Upvotes: 0

Matjaž Drolc
Matjaž Drolc

Reputation: 386

You can use Promises API to solve this problem in an elegant manner.

//call.js
var DataPromise = new Promise(function(resolve, reject) {
    ajaxcall({
          // ...
        }).done(resolve).fail(reject);
   });



//a.js
DataPromise.then(function(data) { console.log("a.js now has the data"); });


//b.js
DataPromise.then(function(data) { console.log("b.js now has the data"); });

The Promises API will take care of tracking what is the status of DataPromise and ensure ajaxcall is issued only once.

Upvotes: 0

Spartacus
Spartacus

Reputation: 1508

Perform your second request in the callback of your first request.

var get = function() {
  var global = [];
    if (Object.keys(global).length)
      retrun global;
    ajaxcall({
      // ...
    }).done(function(data1) {
      global = data1;

      //perform second request here, return data2

    }).fail(function(err) {
    });
  }

Your second request won't execute until the first one has succeeded and invoked its callback.

Upvotes: 0

Gabriel Chiquini
Gabriel Chiquini

Reputation: 106

You can use the async: false in ajax call, but this feature is deprecated. The best idea is create one control var.

   var requestSucceded = false;
   var get = function() {
      var global = [];
        if (Object.keys(global).length && requestSucceded)
          return global;
        ajaxcall({
          // ...
        }).done(function(data) {
          global = data;
          requestSucceded = true;
        }).fail(function(err) {
      });
   }

Upvotes: 1

Related Questions