javascript 从循环中一次发送一个 AJAX 请求

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5066002/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 15:49:31  来源:igfitidea点击:

Sending one AJAX request at a time from a loop

javascriptwaitsynchronous

提问by n4rzul

I know this question has been asked countless times, but I cant figure out for the life of me how to make this answer work in my case: wait for async javascript function to return

我知道这个问题已被问过无数次,但我一生都无法弄清楚如何在我的情况下使这个答案起作用:等待异步 javascript 函数返回

I'm looping through some "tv channels" in the outerloop and then looping through dates in the week in the innerloop. In the inner loop I make a ajax request to a server to fetch the data and I then store/cache it for later use like so

我在外循环中循环播放一些“电视频道”,然后在内循环中循环播放一周中的日期。在内部循环中,我向服务器发出 ajax 请求以获取数据,然后像这样存储/缓存它以备后用

var dates = []; //<-- Contains a list of dates for the coming week 
var baseUrl = "http://www.someserver.com";
var storedChannels = [1,2,3,4,5,6,7,8,9,10,45,23,56,34,23,67,23,567,234,67,345,465,67,34];

for(ch = 0; ch < storedChannels.length; ch++) {   
    var channel = storedChannels[ch];
    for(d=0; d < 7; d++) {
        var currentDate = dates[d];
        ajax({    
            url: baseUrl+"?ch="+channel+"&dt=currentDate"+,
            complete: function(res) {
                CMLocalStore.setString('ch' + ch + "_" + scheduleDay, res);
            },
        });
        //Want to wait here till the ajax request completes.
        //Do not want to continue to next iteration.
        //Do not want to fire of 50 bazillion ajax requests all at once
        //Why? Very limited bandwidth scenario, plenty of channels  
    }
}

PS: NO JQuery please! Plain JS solutions only

PS:请不要使用 JQuery!仅纯 JS 解决方案

Many thanks!

非常感谢!

回答by andynormancx

You want something like this. I haven't tested it, but hopefully you should get the idea.

你想要这样的东西。我还没有测试过,但希望你应该明白。

var dates = []; //<-- Contains a list of dates for the coming week 
var baseUrl = "http://www.someserver.com";
var storedChannels = [1,2,3,4,5,6,7,8,9,10,45,23,56,34,23,67,23,567,234,67,345,465,67,34];

function ProcessNext(ch, d) {
    if (d < 7) {
        d++;
    } else {
        d=0;
        if (ch < storedChannels.length) {
            ch++;
        } else {
            return;
        }
    }

    var channel = storedChannels[ch];
    var currentDate = dates[d];
    ajax({    
        url: baseUrl+"?ch="+channel+"&dt=currentDate"+,
        complete: function(res) {
            CMLocalStore.setString('ch' + ch + "_" + scheduleDay, res);
            ProcessNext(ch, d);
            },
    });
}

ProcessNext(0, 0);

回答by SLaks

You need to turn your loop into a chain of callbacks.

你需要把你的循环变成一个回调链。

Instead of using a loop, you should make your callback call your original function, but with a higher parameter value.

您应该让回调调用原始函数,而不是使用循环,但要使用更高的参数值。

回答by rsp

What you are trying to do is explained in the Asynchronous Iteration Patternstutorial by Pedro Teixeira. The examples are using Node.js but you can use the same patterns in the browser. Basically what you need to do is convert your loops to serial callbacks waiting on each other to complete, so the next AJAX request is fired from the success callback of the previous one etc. It can be done without blocking the browser but not in loops. See that tutorial.

Pedro Teixeira的异步迭代模式教程中解释了您要尝试执行的操作。这些示例使用 Node.js,但您可以在浏览器中使用相同的模式。基本上你需要做的是将你的循环转换为等待对方完成的串行回调,所以下一个 AJAX 请求是从前一个的成功回调等中触发的。它可以在不阻塞浏览器的情况下完成,但不能在循环中完成。看那个教程。

回答by n4rzul

Essentially the answer lies in using recursive calls instead of using loops. Just wanted to add this answer for anyone that might be interested in "for loop nestings" deeper than 2 levels. As you can see its easy to extend to as many "nestings" as you like. Original credit goes to VatooVatooimplementation in Java on the DaniWeb forums.

基本上答案在于使用递归调用而不是使用循环。只是想为可能对 2 级以上的“for 循环嵌套”感兴趣的任何人添加此答案。正如您所看到的,它很容易扩展到任意数量的“嵌套”。原归功于VatooVatoo在DaniWeb论坛,Java实现。

Heres the code, tested and works (without the ajax bits of course but you can add that yourself):

继承人的代码,测试和工作(当然没有ajax位,但你可以自己添加):

<html>
<head>
<script type="text/javascript">
    function loopRecurse(a, b, c)
    {
        if(c >= 2) {
            b++;
            c=0;
            loopRecurse(a, b, c);
            return;
        }
        if(b >= 2) {
            a++;
            b=0;
            loopRecurse(a, b, c);
            return;
        }
        if(a >= 2) return;
        document.write("<div>" + a + "|" + b + "|" + c + "</div>");
        c++;
        loopRecurse(a, b, c);
    }
    loopRecurse(0, 0, 0);
</script>
</head>
<body>
    <!-- output
        0|0|0
        0|0|1
        0|1|0
        0|1|1
        1|0|0
        1|0|1
        1|1|0
        1|1|1
     -->
</body>
</html>

回答by Shadikka

See the XMLHttpRequest documentation(linked to MDC, but shouldn't matter). Basically the condition you're looking for is request.readyState==4- presuming that you have your ajax()return the actual XMLHttpRequestobject.

请参阅XMLHttpRequest 文档(链接到 MDC,但应该无关紧要)。基本上,您正在寻找的条件是request.readyState==4- 假设您ajax()返回了实际XMLHttpRequest对象。