0

I have a piece of code in an app that I am having difficulty pushing items to an empty array. At the beginning of this section, I created some empty array variables.

var sumPOP = [];
var sumRACE = [];
var sumLANG = [];
var sumINCOME = [];

I am going to then iterate through some selected data, so I have a for loop. Within this loop, I am making a call to an api (I know, it's GIS. That's irrelevant. Just pretend it's an ajax call) to retrieve some data. I am able to console.log() the data and it shows up correctly. I then want to push that data (each item in the loop) to the before mentioned empty arrays. Then to test that the array has been populated, I console.log() the array, both within the loop and outside it. My problem is that nothing shows when I console.log the array. Why is the data not getting pushed outside the array? Note: console.log(sumPOP) run within the call function(esriRequest) does show the items pushed to the array:

for (var i=0;i<results.features.length;i++){
            ...
    esriRequest({
        url:"https://api.census.gov/data/2016/acs/acs5",
        content:{
          get: 'NAME,B01003_001E,B02001_001E,B06007_001E,B06010_001E',
          for: `tract:${ACS_TRCT}`,
          in: [`state:${ACS_ST}`,`county:${ACS_CNTY}`]
        },
        handleAs:'json',
        timeout:15000
        }).then(function(resp){
          result = resp[1];
          POP = result[1];
          console.log(POP);
          sumPOP.push(POP);
          RACE = result[2];
          LANG = result[3];
          INCOME = result[4];
          console.log('POP: ' + POP + ', RACE: ' + RACE + ', LANG: '+ LANG + ', INCOME: ' + INCOME);
        }, function(error){
          alert("Data failed" + error.message);
        });
        console.log('POP: ' + sumPOP);
     ...
    }
console.log('POP: ' + sumPOP); 

Additional information: My eventual goal is to get the final array after the selected data has been iterated through and summarize it; or rather, add it together. My expected array results would be sumPOP = [143, 0, 29, 546, 99]; I want apply a function (also outside the loop) to do this:

newSum = function(category) { 
    let nAn = n => isNaN(n) ? 0 : n;  //control for nonNumbers
    return category.reduce((a, b) => nAn(a) + nAn(b))
  };

...and then run popTotal = newSum(sumPOP); to get the total.

1
  • You should add the appropriate tag for the language you're using to the question. Currently, we don't even know what language you're using without looking at the code. Commented Jul 25, 2018 at 16:59

1 Answer 1

1

I believe your data is being pushed, it just appears that it isn't due to the placement of your console.log()'s

Since you are dealing with an async api call, the only place where you are guaranteed to have data is inside your .then() function. Essentially, as you debug, if you add breakpoints, at all your console.log's, you will notice that it hits the ones outside the .then() first and the ones inside the .then() last. Because of that ordering, it will appear that your arrays did not get data pushed to them.

I added some comments to your example code below to illustrate where you should expect to see data.

EDIT: also I made a small adjustment so all the arrays would get populated

EDIT 2: modified the code so it handles multiple async promises in a "synchronous" manner

var sumPOP = [];
var sumRACE = [];
var sumLANG = [];
var sumINCOME = [];
var myPromises = []; // added this new array for promise.all

for (var i = 0; i < results.features.length; i++) {
  var myPromise = esriRequest({
    url: "https://api.census.gov/data/2016/acs/acs5",
    content: {
      get: 'NAME,B01003_001E,B02001_001E,B06007_001E,B06010_001E',
      for: `tract:${ACS_TRCT}`,
      in: [`state:${ACS_ST}`, `county:${ACS_CNTY}`]
    },
    handleAs: 'json',
    timeout: 15000
  });
  myPromises.push(myPromise);

  // because you are making an async request, at this point, sumPOP may be empty
  console.log('POP: ' + sumPOP);
}

Promise.all(myPromises).then(function(resp) {
  result = resp[1];
  POP = result[1];
  console.log(POP); // this will show POP with data


  RACE = result[2];
  LANG = result[3];
  INCOME = result[4];

  sumPOP.push(POP);
  sumRACE.push(RACE); // added this to populate array
  sumLANG.push(LANG); // added this to populate array
  sumINCOME.push(INCOME); // added this to populate array

  // at this point, all your arrays should have data
  console.log('POP: ' + POP + ', RACE: ' + RACE + ', LANG: ' + LANG + ', INCOME: ' + INCOME);
  
  // now that this you have all values, you can call your outside function
  this.handleData();
}, function(error) {
  alert("Data failed" + error.message);
});

// because you are making an async request, at this point, sumPOP may be empty
console.log('POP: ' + sumPOP);

var handleData = function() {
  // do something with the completed data
}

Sign up to request clarification or add additional context in comments.

6 Comments

Your answer is correct in that the console.log functions are in the wrong spot. However, I need to be able to access the array info once it has been populated by data from the final iteration of the loop and then run a function to add all the values inside that array (just regular integers). See my additional information I just added. This was helpful in terms of insight.
Ah okay, so it sounds like you want to do multiple promises and then do an something with the end result. For this, you can use Promise.all().then() or you can switch to using async functions if you don't have any restriction on using ES6.
Here is the link for using async functions: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
OK, the Promise.all method looks like it would work. How would I implement that in the above code?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.