如何在javascript中同步进行两次异步调用?

时间:2017-09-21 19:12:51

标签: javascript jquery ajax asynchronous

我有一个通用的泛型函数,它将用于ajax调用。在第一次触发时,我将从服务器获取整个数据,并且我将保持本地范围。所以在第二次,它不会是服务器的数据。在我的情况下,问题是第一个请求是异步请求,而处理第一个请求第二个请求即将到来,它正在命中服务器。现在,在第一个请求完成之前,如何将第二个请求置于等待状态?

a.js会调用具有ajax调用的call.jsget();

b.js也会调用相同的函数。在第二个数据中,global变量中提供了数据,因此它不会进行任何ajax调用:get();

call.js:

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

在这种情况下,处理第一个请求的第二个请求即将到来。所以它正在打另一个电话。

5 个答案:

答案 0 :(得分:2)

只有一个请求运行到服务器,下一个请求必须等到第一个请求完成

这个问题需要更多行代码,之前已经得到了回答,所以我将链接到几个例子。您应该寻找的是关键字" ajax queue"。

Queue AJAX calls

Sequencing ajax requests

我建议在这种情况下使用一个可用的库,但第一个答案也给出了一些无库代码的例子。

只有一个请求并缓存结果

通常首先要做的就是跟踪你现有的电话。

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) {
});
}

根据您的使用情况,您可能需要在此处进行一些进一步的工作。如果数据已经加载则立即返回数据,如果不是非常理想则不返回任何内容。像这样的东西会更符合通常预期的API设计:

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
 });
}

答案 1 :(得分:1)

您可以在ajax调用中使用async: false,但不推荐使用此功能。最好的想法是创建一个控件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) {
      });
   }

答案 2 :(得分:0)

在第一次请求的回调中执行第二次请求。

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) {
    });
  }

第二个请求不会执行,直到第一个请求成功并调用其回调。

答案 3 :(得分:0)

您可以use Promises API以优雅的方式解决此问题。

//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"); });

Promises API将负责跟踪DataPromise的状态,并确保只发出一次ajaxcall。

答案 4 :(得分:0)

jQuery中的$.ajax函数返回一个jQuery XMLHttpRequest对象或jqXHR。该对象可以存储,并且可以在其上运行函数。

最好的选择是将返回的jqXHR或XMLHttpRequest存储在全局可访问的变量中。在这两个函数中的每个函数中,检查该全局可访问变量是否为null。如果是,则运行它。 ajaxcall完成后,清除varname:

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