Javascript 添加';回调&x27;在一系列异步XHR调用之后

Javascript 添加';回调&x27;在一系列异步XHR调用之后,javascript,jquery,ajax,asynchronous,Javascript,Jquery,Ajax,Asynchronous,我偶然发现了一段Ajax代码,它不是100%安全的,因为它混合了异步/同步类型的代码。。。因此,基本上在下面的代码中,我有一个jQuery.each,它获取元素的信息,并为每个元素启动一个Ajax get请求: $(search).each(function() { $.ajax({ url: 'save.x3?id='+$(this).attr("id")+'value='$(this).data("value"); success: function(o){ //Update

我偶然发现了一段Ajax代码,它不是100%安全的,因为它混合了异步/同步类型的代码。。。因此,基本上在下面的代码中,我有一个jQuery.each,它获取元素的信息,并为每个元素启动一个Ajax get请求:

$(search).each(function() {
 $.ajax({
  url: 'save.x3?id='+$(this).attr("id")+'value='$(this).data("value");
  success: function(o){
   //Update UI
  },
  error: function(o){
   //Update UI
  }
 });
});

//code to do after saving...
显然,“保存后要执行的代码…”通常在所有请求完成之前执行。在理想情况下,我希望服务器端代码一次处理所有请求,并在保存成功回调后移动//代码,但假设这不可能,我将代码更改为类似这样的代码,以确保在继续之前返回所有请求,我仍然不喜欢这些请求:

var recs = [];
$(search).each(function() {
 recs[recs.length] = 'save.x3?id='+$(this).attr("id")+'value='$(this).data("value");
});

var counter = 0;
function saveRecords(){
 $.ajax({
  url: recs[counter],
  success: function(o){
   //Update progress
   if (counter<recs.length){
    counter++;
    saveRecords();
   }else{
    doneSavingRecords();
   }
  },
  error: function(o){
   //Update progress
   doneSavingRecords(o.status);
  }
 });
}

function doneSavingRecords(text){
 //code to do after saving...
}

if (recs.length>0){
 saveRecords();  //will recursively callback itself until a failed request or until all records were saved
}else{
 doneSavingRecords();
}
var recs=[];
$(搜索)。每个(函数(){
recs[recs.length]=“save.x3?id=”+$(this.attr(“id”)+“value=”$(this.data(“value”);
});
var计数器=0;
函数saveRecords(){
$.ajax({
url:recs[计数器],
成功:功能(o){
//更新进度
如果(计数器0){
saveRecords();//将递归回调自身,直到请求失败或保存所有记录为止
}否则{
doneSavingRecords();
}
因此,我正在寻找一种“最佳”方法,向一系列异步调用添加一点同步功能


谢谢!!

如果我理解你的要求,我认为你可以用于此目的。

如果我理解你的要求,我认为你可以用于此目的。

更好的回答:

function saveRecords(callback, errorCallback){
  $('<div></div>').ajaxStop(function(){
    $(this).remove(); // Keep future AJAX events from effecting this
    callback();
  }).ajaxError(function(e, xhr, options, err){
    errorCallback(e, xhr, options, err);
  });

  $(search).each(function() {
    $.get('save.x3', { id: $(this).attr("id"), value: $(this).data("value") });
  });
}
原始答案:如果它们需要按特定顺序排列,或者页面上有其他常规AJAX事件会影响使用
ajaxStop
,这是很好的,但速度会较慢:

function saveRecords(callback){
  var recs = $(search).map(function(i, obj) {
   return { id: $(obj).attr("id"), value: $(obj).data("value") };
  });

  var save = function(){
   if(!recs.length) return callback();

   $.ajax({
    url: 'save.x3',
    data: recs.shift(), // shift removes/returns the first item in an array
    success: function(o){
     save();
    },
    error: function(o){
     //Update progress
     callback(o.status);
    }
   });
  }

  save();
}
然后你可以这样称呼它:

saveRecords(function(){
   // Complete will fire after all requests have completed with a success or error
}, function(e, xhr, options, err){
   // Error will fire for every error
});
saveRecords(function(error){
   // This function will run on error or after all 
   // commands have run
});

更好的回答

function saveRecords(callback, errorCallback){
  $('<div></div>').ajaxStop(function(){
    $(this).remove(); // Keep future AJAX events from effecting this
    callback();
  }).ajaxError(function(e, xhr, options, err){
    errorCallback(e, xhr, options, err);
  });

  $(search).each(function() {
    $.get('save.x3', { id: $(this).attr("id"), value: $(this).data("value") });
  });
}
原始答案:如果它们需要按特定顺序排列,或者页面上有其他常规AJAX事件会影响使用
ajaxStop
,这是很好的,但速度会较慢:

function saveRecords(callback){
  var recs = $(search).map(function(i, obj) {
   return { id: $(obj).attr("id"), value: $(obj).data("value") };
  });

  var save = function(){
   if(!recs.length) return callback();

   $.ajax({
    url: 'save.x3',
    data: recs.shift(), // shift removes/returns the first item in an array
    success: function(o){
     save();
    },
    error: function(o){
     //Update progress
     callback(o.status);
    }
   });
  }

  save();
}
然后你可以这样称呼它:

saveRecords(function(){
   // Complete will fire after all requests have completed with a success or error
}, function(e, xhr, options, err){
   // Error will fire for every error
});
saveRecords(function(error){
   // This function will run on error or after all 
   // commands have run
});
>>在理想的情况下,我希望服务器端代码一次处理所有这些代码,并在保存成功回调后移动//代码

你需要从事件的角度来考虑这一点。 Closure的net.BulkLoader(或类似的方法)将为您提供:

见: goog.net.BulkLoader.prototype.handleSuccess(用于单独调用) & goog.net.BulkLoader.prototype.finishLoad(用于完成所有调用)

>在理想情况下,我希望服务器端代码能够一次处理所有调用,并在保存成功回调后移动//代码

你需要从事件的角度来考虑这一点。 Closure的net.BulkLoader(或类似的方法)将为您提供:

见: goog.net.BulkLoader.prototype.handleSuccess(用于单独调用) &
goog.net.BulkLoader.prototype.finishLoad(用于完成所有调用)

通过调用相同的函数来检查所有AJAX调用是否完成,这很容易解决。您只需在函数之间共享一个简单的队列,并快速检查(无循环、计时器、承诺等)

//我们将为其发出异步请求的URL列表
var queue=['/something.json','/other.json'];
//将包含我们的返回数据,以便我们可以使用它
//在我们最后的统一回调中(本例中为“displayAll”)
var数据=[];
//处理队列,分派请求,检查是否完成
函数processQueue(队列){
对于(变量i=0;i

编辑:我应该补充一点,我专门针对队列中任意数量的项目。您只需添加另一个URL,效果也一样。

通过调用相同的函数来检查所有AJAX调用是否完成,这很容易解决。您只需在函数之间共享一个简单的队列,并进行快速检查(没有循环、计时器、承诺等)

//我们将为其发出异步请求的URL列表
var queue=['/something.json','/other.json'];
//将包含我们的返回数据,以便我们可以使用它
//在我们最后的统一回调中(本例中为“displayAll”)
var数据=[];
//处理队列,分派请求,检查是否完成
函数processQueue(队列){
对于(变量i=0;i