2

I have a series of nested Ajax requests to external APIs, which is very ugly but it was the only way I could figure out how to make calls in a specified order with each call utilizing some values brought back from the previous call. (I attempted this but couldn't get it to work, so I reverted to the advice here.)

Anyway, this works well to a point. All my calls work in succession, and I end up with an array called people, which is just a list of names: ["name1","name2","name3"].

My problem is that I don't seem to be able to do anything with this array from my javascript code. I can't append them to a div, nor can I alert them, or even console.log them during code execution. However, once my code completes, I can type people into the browser console and there they all are, as expected.

I am guessing this has something to do with the scope of the variable - I have tried making it global and moving the placement of its declaration, but the only way I can access people from the runnable code is from within the final AJAX loop, and then I get lots of repeating values because it's looping and adding to the array incrementally.

The goal here is to get people from that final API call and list them in HTML.

Here's my code. Any suggestions greatly appreciated.

HTML to trigger event:

<input type='file' accept='image/*' onchange='openFile(event)'>
<!--process is triggered by file upload-->

javascript:

    var openFile = function(event) {

    //... Some UI stuff happens here.
    //... When finished, just call getGraph(); below

    performances = new Array();  // global scope
    people = new Array();  // global scope
    getGraph();  // call function below

    console.log(people);   // retrieve array; doesn't work
  };  

   function getGraph(){ 
    $.ajax({
       url:'http://...' + document.getElementById('prDate').value,
       dataType:'json',
       success: function(response){
           $.each(response, function(i, item) {
               var programID = item.id;
                 $.ajax({
                    url:'http://...'+ programID',
                    dataType:'json',
                    success: function(response){
                        $.each(response, function(i, item) {
                            performances.push( item.id );
                        });
                        $.each(performances, function(index, value){
                            $.ajax({
                               url:'http://...' + this.valueOf() +'/persons/',
                               dataType:'json',
                               success: function(response){
                                   $.each(response, function(i, item) {
                                       people.push( item.firstname + ' ' + item.lastname );  // the magic moment
                                    }); 
                                } 
                            }); 
                        }); 
                    }
                });
            });
        }
    }); 
} 
Community
  • 1
  • 1
mjb363
  • 21
  • 1
  • possible duplicate of [How to return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Tibos May 16 '15 at 05:09
  • AJAX calls are asynchronous and henceforth responses are accessible only through callbacks, so in the final success callback you can pass the people array as a parameter to a function which then renders the html based upon it. – Ramanathan Muthuraman May 16 '15 at 05:11
  • from the looks of your code it seems people is only accessible after `openFile` is invoked. Have you tried `people = new Array();` outside of the `openFile`? – imGreg May 16 '15 at 05:13

2 Answers2

0

From your code it is visible that people variable will be create only once you call openfile function. If you want it be created even when the openfile method is not called then declare it outside of all the functions and then it will be accessible or else declare it in the place where you intend to use it like above the ajax call, then use it.

Sourabh Kumar Sharma
  • 2,864
  • 3
  • 25
  • 33
0

Have you tried putting it inside a IIFE closure ?

(function(){

  var OpenFile = function() {

    if ( !(this instanceof OpenFile) ) {
      return new OpenFile();
    }

    var performances = new Array();   // closure Scope
    var people = new Array();         // closure Scope

    function getGraph(){ 
      $.ajax({
         url:'http://...' + document.getElementById('prDate').value,
         dataType:'json',
         success: function(response){
             $.each(response, function(i, item) {
                 var programID = item.id;
                   $.ajax({
                      url:'http://...'+ programID',
                      dataType:'json',
                      success: function(response){
                          $.each(response, function(i, item) {
                              performances.push( item.id );
                          });
                          $.each(performances, function(index, value){
                              $.ajax({
                                 url:'http://...' + this.valueOf() +'/persons/',
                                 dataType:'json',
                                 success: function(response){
                                     $.each(response, function(i, item) {
                                         people.push( item.firstname + ' ' + item.lastname );  // the magic moment
                                      }); 
                                  } 
                              }); 
                          }); 
                      }
                  });
              });
          }
      }); 
    }

    return {
      get performances() : { return performances;},
      get people()       : { return people; },
      getGraph           : getGraph
    };
  };

  window.OpenFile = OpenFile;

})();

which you can then call by doing something like

var myOpenFile = new OpenFile();

var people = myOpenFile.people;

myOpenFile.getGraph();

console.log(people);

with the added benefit that the OpenFile object is immediately available after the code loads. All the variables inside the code are only scoped to the object OpenFile and don't pollute the global namespace and you can choose what you wish to expose to others by putting them in the return statement at the end.

Code Uniquely
  • 6,356
  • 4
  • 30
  • 40