0
var info = [];
var data = [];
var ids;

function loadData() {

  d3.json('data/res/ID.json', function (error, d) {
    ids = d.ids;
    d.ids.forEach(function (id, i) {

        d3.json('data/res/json/' + id + '.json', function (error, d) {
            info.push({
                "id": id,
                "value": d
            })
        })
    });

    initMap(ids, info);

  });


}

I simply want to read from several csv files and create an array of object in var info. Then I want to pass the array to a function called initMap(). However, when I console.log(info) in initMap(), it shows an empty array.

I am really confused by the order of the execution of functions. What should to do if I want to make sure that var info is done before passed to initMap()?

Sophie
  • 9
  • 3
  • Have you debugged the response while pushing data into info array? Does that ajax call return any response data? Does that ID.json returns any data? – Namdeo Karande Apr 25 '17 at 04:50
  • 2
    [How do I return the response from an asynchronous call?](//stackoverflow.com/q/14220321) – Tushar Apr 25 '17 at 04:50
  • `function loadData() { d3.json('data/res/ID.json', function (error, d) { var ids = d.ids; var info = []; d.ids.forEach(function (id, i) { d3.json('data/res/json/' + id + '.json', function (error, d) { info.push({ "id": id, "value": d }) }) }); console.log(ids, info); }); }` – Rayon Apr 25 '17 at 04:55
  • 4
    There's two types of javascript programmers. the other does not. One that understands asynchronous code, – Jaromanda X Apr 25 '17 at 05:09
  • 1
    @JaromandaX: I like that one :D – Felix Kling Apr 25 '17 at 05:09
  • @JaromandaX, that's priceless, I'm gonna use it. – Gerardo Furtado Apr 25 '17 at 07:20

1 Answers1

0

It seems that data is pushed to info asynchronously in a callback, while initMap is called synchronously right after d.ids.forEach. In other words, d.ids.forEach schedules pushing data to info, and initMap is called before scheduled actions are executed.

You will need to track d3.json('data/res/json/' + id + '.json' callback execution (i.e. using a counter) and trigger initMap after all callbacks are executed.

It may look like (untested, just trying to reflect the idea):

var itemsAmount = d.ids.length;
var cbExecuted = 0;
d.ids.forEach(function (id, i) {

        d3.json('data/res/json/' + id + '.json', function (error, d) {
            info.push({
                "id": id,
                "value": d
            });
            if (++cbExecuted === itemsAmount) initMap(ids, info);
        })
    });
Alina Loi
  • 184
  • 6
  • This is really helpful! My codes work now! Thanks! I am only a beginner in Javascript. Seems callback is a must in the asynchronous execution. – Sophie Apr 25 '17 at 15:08