【问题标题】:Using deferred to chain loops with multiple ajax calls使用 deferred 链接具有多个 ajax 调用的循环
【发布时间】:2014-04-02 18:17:26
【问题描述】:

已经有多个问题对此有了答案,但到目前为止,这种设置都无法正常工作。

function login(u,p) {
   console.log(1);
   return $.post(url, {u,p});
}

function out() {
   console.log(3);
   //a function that does not return deferred
   // clear cookies
}

function doSomething() {
  console.log(2);
  // a function that returns a deferred
  return $.post(...);
}
var data = [{u: 'au', p: 'ap'}, {u: 'bu', p: 'bp'}]

$.each(data, function(k,v){
  login(v.u, v.p).then(doSomething).then(out);
});

我期待它的顺序是这样的:

1
2
3
1
2
3

但我明白了

1
2
1
3
2
3

为什么会这样,即使我正在等待使用 then 解决的承诺

【问题讨论】:

  • $.each(data, function(k,v){ 没有等待下一次迭代的承诺。
  • 那我该如何等待。
  • 我不确定正确的方法是什么,但我会尝试使用一个递归函数,它在链 .then(theFunction(data)); 的末尾调用自身,并将一个元素移出数组 data 每个时间到没有了。
  • 我想这是我上次做的,我会试试的
  • 根据 AJAX 调用所花费的时间,它们可能不会按照它们被触发的顺序返回。

标签: javascript jquery ajax jquery-deferred


【解决方案1】:

如果您希望登录同步运行:

var p = new jQuery.Deferred();
$.each(data, function(k,v){
  p.then(function() {
    return login(v.u, v.p);
  }).then(doSomething).then(out);
});

$.each 中迭代的每个新项目在 p 完成最后一个之前不会触发新响应。

【讨论】:

    【解决方案2】:

    这个想法是像@Popnoodles 提到的那样创建一个递归函数。

    例如

    function a() {
      return $.post();
    }
    
    function b() {
      return $.post();
    }
    
    function c() {
       console.log('no promise.');
    }
    
    // and the recursive main function
    
    function main() {
       if(counter < data.length){
          $.when(a().then(b).then(c)).done(function(){
            counter++;
            main();
          });
       }
    }
    
    main();
    

    Here is how it works,打开控制台看看它是如何按顺序记录函数的。

    【讨论】:

    • 是否有可能做到这一点并传递一个 a 会返回给 b 的值?或者我需要为此使用全局变量。
    猜你喜欢
    • 2013-04-27
    • 2018-03-24
    • 2015-06-25
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    • 2012-01-27
    • 1970-01-01
    • 2015-02-16
    相关资源
    最近更新 更多