LinCR
LinCR

Reputation: 401

call two ajax function inside each other

i have an ajax call and it works good , when i call a new ajax call inside the old one , i got error in the first call

just one ajax call

$.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>');
            }
        });

after adding this ajax call

$.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>');
                });
            }
        });

after that , the concepts[i] and the relations[i] will be as undifined and the data1.length always null and the this is the second php code for ajax

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);
        }
    }

and i tried it and it works good

Upvotes: 0

Views: 396

Answers (2)

Alnitak
Alnitak

Reputation: 339776

You can't use a loop variable ( i in your case) inside a callback function - it'll have whatever value it had when the loop terminated by the time your async callback function is invoked.

As you're already using jQuery, you might as well use $.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!

        });
    });
});

which will ensure that i is correctly bound to the current iteration number each time.

Upvotes: 4

nnnnnn
nnnnnn

Reputation: 150010

The reason that concepts[i] and the relations[i] are undefined within the callback function of the inner $.getJSON() function is that $.getJSON() is aysnchronous which means that the entire for loop will have finished running before any of the callbacks occur on the inner $.getJSON() calls - so by the time these inner callbacks occur i is one higher than the maximum index of the concepts and relations arrays.

To get around this you can introduce an extra closure to keep the values from each iteration:

$.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]);
   }
});

The anonymous function I've added inside the for loop will run once per iteration creating separate closures each with their own currentConcept and currentRelation.

EDIT: To make it really obvious what I've changed compared to your original code--

Add the following line as the first thing inside your existing for loop:

   (function(currentConcept, currentRelation) {

And then the following line as the last thing before your existing for loop's closing }:

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

And then everywhere inside the for loop where you did have concepts[i] and relations[i] change them to currentConcept and currentRelation.

Upvotes: 3

Related Questions