Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript如何确定何时在循环中完成AJAX调用_Javascript_Jquery_Ajax - Fatal编程技术网

JavaScript如何确定何时在循环中完成AJAX调用

JavaScript如何确定何时在循环中完成AJAX调用,javascript,jquery,ajax,Javascript,Jquery,Ajax,在过去的几天里,我一直在努力解决这个问题,并在StackOverflow和其他网站上阅读了各种解决方案 我正在构建一个站点,该站点从外部源获取XML数据,然后根据结果获取更多XML以构建网络图问题是,我必须等到这个AJAX调用循环(可能会循环成更多的AJAX调用)完成后才能绘制 我不知道这是否只是一个特别高的认知负荷,但它确实让我感到困惑 我的代码: function cont(outerNodes) { for (var i = 0; i < outerNodes.length

在过去的几天里,我一直在努力解决这个问题,并在StackOverflow和其他网站上阅读了各种解决方案

我正在构建一个站点,该站点从外部源获取XML数据,然后根据结果获取更多XML以构建网络图问题是,我必须等到这个AJAX调用循环(可能会循环成更多的AJAX调用)完成后才能绘制

我不知道这是否只是一个特别高的认知负荷,但它确实让我感到困惑

我的代码:

function cont(outerNodes) {

    for (var i = 0; i < outerNodes.length; i++) {
        var node = outerNodes.pop();
        getXML(node["label"], node["id"]);
    } 
    // I want the code to wait until loop is done, and then draw.
    draw(nodes, edges);
}

function getXML(term, fromId) {

    var url = someURL;
    $.ajax({
        url: url,
        dataType: "xml",
        success: function(result) {
            var outerNodes = process(result, fromId, term);
            cont(outerNodes);
        }
    });

}
功能控制(外部节点){
对于(变量i=0;i
注意:我理解我可能完全误解了JavaScript的同步性,我很可能是这样。在过去,我成功地使用了回电和承诺,但我似乎无法理解这一点

如果我还不完全清楚,请让我知道

我确实尝试过实现在process()函数中递增的排序计数器,如下所示:

if (processCount < 15) {
    for (var i = 0; i < outerNodes.length; i++) {
        var node = outerNodes.pop();
        getXML(node["label"], node["id"]);
    }
} else {
    draw(nodes, edges);
}
if(进程计数<15){
对于(变量i=0;i

然而,这最终导致了几次draw()调用,这使我的性能非常糟糕。

如果在多次测试之后,您知道它不会超过5秒。。。您可以使用setTimeout

function cont(outerNodes) {

        for (var i = 0; i < outerNodes.length; i++) {
            var node = outerNodes.pop();
            getXML(node["label"], node["id"]);
    } 


// Display a 5 second progress bar here

 setTimeout(function(){ draw(nodes, edges); },5000); 

}
功能控制(外部节点){
对于(变量i=0;i
解决此问题的最佳方法应该是使用承诺或回调。 如果你真的想避免承诺或回访(尽管我不知道为什么…) 你可以用柜台试试

    let processCount = 0;
    
    // Increasing the processCount in getXML callback method
    function getXML(term, fromId) {
        var url = someURL;
        $.ajax({
            url: url,
            dataType: "xml",
            success: function(result) {
                processCount++;
                var outerNodes = process(result, fromId, term);
                cont(outerNodes);
            }
        });

    }

    for (var i = 0; i < outerNodes.length; i++) {
        var node = outerNodes.pop();
        getXML(node["label"], node["id"]);
    }
    while (processCount < outerNodes.length) {
        // do nothing, just wait'
    } 

    draw(nodes, edges);
让processCount=0;
//增加getXML回调方法中的processCount
函数getXML(术语,fromId){
var url=someURL;
$.ajax({
url:url,
数据类型:“xml”,
成功:功能(结果){
processCount++;
var outerNodes=过程(结果、fromId、术语);
续(外节点);
}
});
}
对于(变量i=0;i
我们可以使用支持良好的新API和语言结构。和

fetchapi使用承诺。可以期待承诺。
for…of
循环知道
等待
并且在
等待
通过之前不会继续循环

// Loop through, one-at-a-time
for (const node of outerNodes) {
  // Make the HTTP request
  const res = await fetch(someUrl);
  
  // Do something with the response here...
}

不要忘记一个
尝试
/
捕获
(它也适用于
等待
),然后检查。

Brad的回答将代码更改为同步,对我来说,这违背了目的。如果您一直在等待所有请求完成,那么可能需要一段时间,而普通浏览器可以处理多个请求

你在最初的问题中遇到的问题是范围问题。因为每次调用
cont(outerNodes)
都会触发它自己的作用域,所以它不知道这些调用在做什么。因此,基本上,如果您调用
cont(outerNodes)
两次,每个调用都将处理自己的
outerNodes
列表,然后调用
draw
。 解决方案是在不同的作用域之间共享信息,这可以用一个但最好是两个全局变量来完成:一个用于跟踪活动进程,一个用于跟踪错误

var inProcess = 0;
var nrErrors = 0;

function cont(outerNodes) {

    //make sure you have outerNodes before you call outerNodes.length
    if (outerNodes) {
      for (var i = 0; i < outerNodes.length; i++) {
          var node = outerNodes.pop();
          inProcess++; //add one more in process
          getXML(node["label"], node["id"]);
      } 
    }

    //only trigger when nothing is in proces. 
    if (inProcess==0) {
      // I want the code to wait until loop is done, and then draw.
      draw(nodes, edges);
   }
}

function getXML(term, fromId) {

    var url = someURL;
    $.ajax({
        url: url,
        dataType: "xml",
        success: function(result) {
            var outerNodes = process(result, fromId, term);
            inProcess--; //one is done
            cont(outerNodes);
        },
        error: function() {
            inProcess--; //one is done
            nrErrors++; //one more error
            cont(null); //run without new outerNodes, to trigger a possible draw
        }
    });

}
var-inProcess=0;
var nErrors=0;
功能控制(外部节点){
//在调用outerNodes.length之前,请确保您有outerNodes
if(外节点){
对于(变量i=0;i
请注意,我跟踪
nErrors
,但不做任何处理。您可以使用它一起停止进一步的处理,或者警告用户绘制未完成

[重要]请记住,这在
javascript
中有效,因为它最多只能模拟多线程。这意味着调用
inProcess--然后紧接着
cont(外部节点)总是在彼此之后直接执行

如果要将其移植到真正的多线程环境中,很可能是
cont(null)的另一个作用域/版本将插入