【问题标题】:While or For loop with an AJAX query带有 AJAX 查询的 While 或 For 循环
【发布时间】:2015-02-08 23:03:04
【问题描述】:

我正在尝试使用 while 或 for 循环来控制 ajax 查询。我的意图是让循环执行 4 次并用相同的查询填充 4 个值。我遇到的问题是,当然,AJAX 请求是异步的并且可能需要时间。所以我要么最终得到一个冻结的浏览器,要么是一个在分配值之前完成的循环。

var i = 0;
while (i < 4) {
    doAjaxReq().done(function (result) {
        if (i == 0) val1 = result;
        else if (i == 1) val2 = result;
        else if (i == 2) val3 = result;
        else if (i == 3) val4 = result;
    });
}

如果我将 i++ 放在 ajax 请求之外,它当然会在所有请求完成之前完成循环。如果我将 i++ 放在 ajax.done() 中,我会崩溃浏览器。

我能做什么?

【问题讨论】:

  • 为什么不用数组来放结果?
  • 我不知道会有什么不同..我仍然需要 4 个 ajax 调用。
  • 你能试试递归吗?
  • 你永远不会增加i - 这会永远运行吗?
  • 有更好的方法给猫剥皮。您可以将上下文传递给 ajax 调用(在回调含义中给出this(例如this=val1,或this=val2))。另外,可能想查看$.Deferred API。

标签: jquery ajax


【解决方案1】:

.done() 处理程序稍后会被调用。这意味着您的 forwhile 循环将完全完成,i 将处于其最终值。因此,您要么必须找到不同的结构,要么必须将 i 放入闭包中,以保留其价值。执行哪一个取决于您是否真的希望并行或按顺序运行 ajax 调用。

如果并行正常(所有 ajax 调用同时进行),那么您有以下选择:

for (var i = 0; i < 4; i++) {
    // create closure to capture the value of `i`
    (function(index) {
        doAjaxReq().done(function (result) {
            if (index == 0) val1 = result;
            else if (index == 1) val2 = result;
            else if (index == 2) val3 = result;
            else if (index == 3) val4 = result;
        });
     })(i);
}

或者,将结果放入数组并使用 promise 函数知道一切何时完成可能会使编码更容易:

var promises = [];
for (var i = 0; i < 4;i++) {
    promises.push(doAjaxReq());
}
$.when.apply($, promises).done(function(r1, r2, r3, r4) {
    // all ajax calls are done here and 
    // results are in r1[0], r2[0], r3[0], r4[0]
});

如果您尝试一个接一个地对 ajax 调用进行排序(等待一个完成,然后再启动下一个),那么您可以使用以下结构:

 var cntr = 0;
 var results = [];
 function next() {
     doAjaxDone().done(function(data) {
         ++cntr;
         results.push(data);
         if (cntr < 4) {
             next();
         } else {
             // all ajax calls done here and results are in results array
         }
     })
 }

【讨论】:

  • @dave - 你是对的 - 我已经更正了。这种疏忽导致它不直接支持数组,因为这是最常见的用法。
【解决方案2】:

试试:

   function request(i){
      if(i> 3) return;

    doAjaxReq().done(function (result) {
            if (i == 0) val1 = result;
            else if (i == 1) val2 = result;
            else if (i == 2) val3 = result;
            else if (i == 3) val4 = result;

              request(i+1);
        });
    }

//somewhere
request(0);

【讨论】:

  • 我最终使用了这个的变体并且它有效。我只是使用了递归,如果我点击它 4 次,我就返回了
【解决方案3】:

我不知道这是否是最好的解决方案,但我想不出更简单的方法

var i = 0;
var results = [];

function xx(){

    if(i >= 4){
        return;
    } else {

        doAjaxReq().done(function (result) {        
            //avoid if and elseif
            results[i] = result;

            i++;
            xx();
        });

    }

}

}

【讨论】:

  • 从不增加i 并一次运行所有调用,从而混合i 的所有值。
  • 现在,它将所有结果放入results[3]。也不是打电话给xx()
  • @jfriend00 忘记添加增量,而不是对函数的初始调用,我只提供递归函数。我不理解 mixing values 的部分,我认为 op 试图将每个响应存储在一个单独的变量中。这个fiddle 正在工作并将所有值放在数组的单独索引中。
  • 那是因为你的 jsFiddle 不是异步的,这是这里的挑战。 .done() 处理程序将在您的所有xx() 函数调用都被调用之后的某个时间被调用。这意味着当您的所有 .done() 处理程序被调用时,i 的值将是 3。这是异步响应的全部问题。如果您将 i++xx() 移动到 .done() 处理程序中,那么它可能会起作用。
  • 哦,好的,这就是问题所在。我要改变它。谢谢
【解决方案4】:

试着把你的结果放在一个像

这样的 n 数组中
var i = 0;
var ajaxRes=[];
while (i < 4) {
    doAjaxReq().done(function (result) {
       ajaxRes.push(result);
    });
    i++
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-01
    • 1970-01-01
    • 2020-06-12
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    • 2022-01-19
    相关资源
    最近更新 更多