3

SOLVED: I solved my problem by doing each XMLHttpRequiest() recursively. Basically at the end of my xhr.onload, I would make another request and actively check if I've reach the end of my data - when I have I return.

I'm fairly new in JavaScript and have some familiarity with the D3 Library. I'm trying to read a CSV file from my computer using the D3 Library and sending specific information from my file to an API through an XMLHttpRequest().

With each call to the API which returns a JSON object to me, I store that object in a dataset for later use. I'm trying to have it so that my whole CSV file is read and processed before I work with the dataset, however I'm running into a problem since the API calls are asynchronous.

My code looks something like this:

var myData = [];

d3.csv("myFile.csv", function(data)
{
    for (var i = 0; i < data.length; i++)
        // Get appropriate data from data object
        // Make API call with XMLHttpRequest() and store in myData array
});

// Handle fully updated myData array here

As it is, my code currently goes through my loop in almost an instant and makes all the API calls asynchronously and then proceeds to work on my data without waiting for anything to update.

Is there a way to ensure that my CSV file has been processed and all the API calls have returned before I can work with this dataset? I've tried callback functions and promises but had no success.

  • If you solved your question, post the solution as an answer here for other to refer in future. – Sam May 18 '17 at 19:36

2 Answers2

3

You can easily do this with a simple counter

var counter = 0;
var myData = [];

d3.csv("myFile.csv", function(data)
{
  for (var i = 0; i < data.length; i++){
  // Get appropriate data from data object
    $.get("your/api/path", function(result){
      counter++;  // this is important. It increments on each xhr call made.
      myData.push(result); 
      if(counter === data.length) cb(myData); // This will check if the current xhr request is the last xhr request. If yes then call our cb function.
    });
  }
});

function cb(data){
  // This will run only when all the http requests are complete
  // Do something with data
}

All this code does is, it makes sure that all of our requests should be completed first before calling our cb function (here you will write your further logic). This approach guarantees that cb will run only when all xhr requests are completed.

Sam
  • 317
  • 3
  • 12
0

I think the answer in this post could help d3: make the d3.csv function syncronous

You can as well use the Promise API.

Community
  • 1
  • 1
orabis
  • 2,749
  • 2
  • 13
  • 29