异步请求链

时间:2013-12-19 21:17:08

标签: javascript jquery ajax asynchronous

我正在寻找有关链接ajax请求的a previous accepted answer扩展的建议。

提出了以下异步链解决方案来对3个ajax请求进行排序:

var step_3 = function() {
    c.finish();
};

var step_2 = function(c, b) {
    ajax(c(b.somedata), step_3);
};

var step_1 = function(b, a) {
  ajax(b(a.somedata), step_2);
};

ajax(a, step_1);

这对于预定数量的链式ajax函数很有用,但对于可变数量的此类函数的情况不能很好地扩展。

我尝试过以下操作但似乎因为我承认缺乏javascript专业知识而遇到了范围问题:

var asynch      = function (options, fNext) {// do something asynchronously} 
var chain       = {f:[]} // chain of asynchronous functions
var args        = function(n){ //return arguments to feed n'th asynch function }
for (n=0;n<N;n++) 
{
    var a       = args(n);
    var ftmp    = n==N-1? function(){} : chain.f[n+1]
    chain.f[n]  = function () {asynch(a, ftmp)}
}
chain.f[0]()  // initiate asynchronous chain

2 个答案:

答案 0 :(得分:0)

异步循环是一个痛苦的屁股。根据经验,如果你想手动完成它们,你需要将for循环重写为递归函数。

function sequence_synchronous(steps){
  for(var i=0; i<steps.length; i++){
    steps[i]();
  }
  return;
}


function sequence_async(steps, callback){
  var i = 0;
  var next_step = function(){
    if(i >= steps.length){
       callback();
    }else{
       steps[i](function(){
          i++;
          next_step();
       });
    }
  }
  next_step();
}

请注意,在调用第一个回调函数之前,这并不会尝试构建一大串回调 - 我们所做的就是将传统的for循环转换为continuation传递样式。

我强烈建议你找一个图书馆为你做这件事。

答案 1 :(得分:0)

你所拥有的是for循环的一个非常常见的范围问题。 for循环的每次迭代都使用与父函数相同的局部作用域,这意味着异步发生的任何内容都将最终访问循环的最后一个值而不是定义它时的值。请参阅此小提琴作为示例:http://jsfiddle.net/GAG6Q/而不是asynch被调用9次,它被调用一次,值为9.您可以通过简单地为循环内部提供私有范围来修复它。您还需要将chain.f[n+1]包装在一个函数中,这样就不会尝试将undefined赋值给ftmp

http://jsfiddle.net/GAG6Q/1/

var N = 10;
var asynch      = function (options, fNext) {
    console.log(options);
    setTimeout(fNext,500);
}// do something asynchronously} 
var chain       = {f:[]} // chain of asynchronous functions
var args        = function(n){return n;} //return arguments to feed n'th asynch function }
for (n=0;n<N;n++) 
{
    (function(n){
        var a       = args(n);
        var ftmp    = n==N-1? function(){} : function(){chain.f[n+1]();};
        chain.f[n]  = function () {asynch(a, ftmp)}
    })(n);
}
chain.f[0]()  // initiate asynchronous chain