0

我有一个 ajax 调用,它工作得很好,当我在旧的调用中调用一个新的 ajax 调用时,我在第一次调用时出错了

只有一个ajax调用

$.getJSON("http://localhost/Mar7ba/Ontology/getRelatedConceptsAndRelations/"+conceptName+"/TRUE",function(data){
            var concepts = data[0];
            var relations = data[1];
            for(var i = 0 ; i < concepts.length ; i++){
                var IOS = '';
                $("#ioAddRelatedConcepts").append('<p>\n\
                  connect to\n\
                  <span class="ioAddConcept">'+concepts[i]+'</span>\n\
                  with\n\
                  <span class="ioAddRelation">'+relations[i]+'</span>\n\
                  <select name ="concetedIOs[]" class="TypeSelector">\n\
                  '+IOS+'</select>\n\
                  <span class="errorMessage"></span>\n\
                  <a href="#" class="removeA" id="aioRemoveIO">remove</a>\n\
                </p>\n\
                  <p>');
            }
        });

添加此 ajax 调用后

$.getJSON("http://localhost/Mar7ba/Ontology/getRelatedConceptsAndRelations/"+conceptName+"/TRUE",function(data){
            var concepts = data[0];
            var relations = data[1];
            for(var i = 0 ; i < concepts.length ; i++){
                $.getJSON("http://localhost/Mar7ba/InformationObject/getIOsForConcept/"+concepts[i]+"/TRUE",function(data1){
                    var IOS = '';
                    $("#ioAddRelatedConcepts").append('<p>\n\
                  connect to\n\
                  <span class="ioAddConcept">'+concepts[i]+'</span>\n\
                  with\n\
                  <span class="ioAddRelation">'+relations[i]+'</span>\n\
                  <select name ="concetedIOs[]" class="TypeSelector">\n\
                  '+IOS+'</select>\n\
                  <span class="errorMessage"></span>\n\
                  <a href="#" class="removeA" id="aioRemoveIO">remove</a>\n\
                </p>\n\
                  <p>');
                });
            }
        });

之后,概念[i] 和关系[i] 将是未定义 的,并且 data1.length 始终为空 ,这是 ajax 的第二个 php 代码

public function getIOsForConcept($conceptName, $AJAX) {
        if ($AJAX) {
            $results = $this->model->getIOsForConcept($conceptName);
            $IOs = array();
            $i = 0;
            while ($row = $results->fetch()) {
                $IOs[$i] = $row['name'];
                $i++;
            }
            return json_encode($IOs);
        }
    }

我试过了,效果很好

4

2 回答 2

4

您不能在回调函数中使用循环变量(i在您的情况下) - 在调用异步回调函数时循环终止时,它将具有任何值。

由于您已经在使用 jQuery,您不妨使用$.each()

$.getJSON(..., function(data) {

    var concepts = data[0];
    var relations = data[1];

    $.each(concepts, function(i, value) {

        // concepts[i] is OK to use now, and is also in "value"
        // relations[i] is OK to use too

        $.getJSON(..., function() {

            // you can still use them here, too!

        });
    });
});

这将确保i每次都正确绑定到当前迭代次数。

于 2012-05-20T11:17:50.353 回答
3

内部函数的回调函数中未定义concepts[i]和 的原因是异步的,这意味着整个 for 循环将在内部调用发生任何回调之前完成运行 - 所以当这些内部回调发生时比和数组的最大索引高一。relations[i]$.getJSON()$.getJSON()$.getJSON()iconceptsrelations

为了解决这个问题,您可以引入一个额外的闭包来保留每次迭代的值:

$.getJSON("http://localhost/Mar7ba/Ontology/getRelatedConceptsAndRelations/"+conceptName+"/TRUE", function(data){
   var concepts = data[0];
   var relations = data[1];
   for(var i = 0 ; i < concepts.length ; i++){
      (function(currentConcept, currentRelation) {
         $.getJSON("http://localhost/Mar7ba/InformationObject/getIOsForConcept/"+currentConcept+"/TRUE" , function(data1){
            var IOS = '';
            $("#ioAddRelatedConcepts").append('<p>\n\
              connect to\n\
              <span class="ioAddConcept">'+ currentConcept +'</span>\n\
              with\n\
              <span class="ioAddRelation">'+ currentRelation +'</span>\n\
              <select name ="concetedIOs[]" class="TypeSelector">\n\
              '+IOS+'</select>\n\
              <span class="errorMessage"></span>\n\
              <a href="#" class="removeA" id="aioRemoveIO">remove</a>\n\
              </p>\n\
              <p>');
         });
      })(concepts[i], relations[i]);
   }
});

我在 for 循环中添加的匿名函数将在每次迭代时运行一次,创建单独的闭包,每个闭包都有自己的currentConceptand currentRelation

编辑:为了让我与您的原始代码相比,我所做的更改非常明显 -

for在现有循环中添加以下行作为第一件事:

   (function(currentConcept, currentRelation) {

然后将以下行作为现有for循环关闭之前的最后一件事}

    })(concepts[i], relations[i]);

然后for在你确实拥有的循环内的任何地方concepts[i],并将relations[i]它们更改为currentConceptand currentRelation

于 2012-05-20T11:17:38.310 回答