0

I have an object I want to pass on to functions and manipulate called spots

My setDistances function does just that.

After the function I'll console.log the manipulated value like this console.log('DistanceFrom Set. ' + distSetSpots[0].distanceFrom); & it'll appear that the value hasnt been changed.

Whats weird is if i console.log the entire object like this console.log(distSetSpots); & transverse through it via chrome dev tools instead of programactically, it'll in fact be show the manipulated value.

This has left me pretty confused.. Can anyone explain whats happening here? Full relevant code below:

    // Get a copy of the Spots data in spots.json
this.sds.fetchData( (spots) => {
  // Get distance inbetween each spot & the user's location
    this.lcs.setDistances(spots, (distSetSpots) => {
      console.log(distSetSpots);
      console.log('DistanceFrom Set. ' + distSetSpots[0].distanceFrom);
      // 'Filter' spots (set 'pts' to null) that exceed max distance
      this.filterFarSpots(distSetSpots, (filteredSpots) => {
        // Find matched target species in spots & assign pts
        this.findTargetSpecies(filteredSpots, (prefTargSpots) => {
        });
      });
    });
  }
);

setDistances function:

setDistances(spots, callback) {
  const posRef = this.posObject;
  for (let i = 0; i < spots.length; i++) {
    const origin = new google.maps.LatLng(posRef.pos.coords.latitude, posRef.pos.coords.longitude);
    const destination = new google.maps.LatLng(spots[i].coords[0], spots[i].coords[1]);
    const service = new google.maps.DistanceMatrixService();
    service.getDistanceMatrix({
      origins: [origin],
      destinations: [destination],
      travelMode: 'DRIVING',
    }, (resp, status) => {
      spots[i].distanceFrom = (resp.rows[0].elements[0].distance.value / 1000).toFixed(1);
    });
  }
  callback(spots);
}
Cody G
  • 8,368
  • 2
  • 35
  • 50
Snar3
  • 68
  • 1
  • 11
  • Probably need to see your `setDistances` code. – Cody G Dec 31 '17 at 04:49
  • 2
    You're calling `callback(spots);` immediately in `setDistances` before spots has been updated. Chrome console shows the correct thing when you log the whole object because it shows you the state of the object at the time you expand it in the console, not the time it was logged. – Paul Dec 31 '17 at 04:55
  • 1
    Accessing the Distance Matrix service is asynchronous, so you'll need to handle this in either one or two ways. Process each request at a time, or process them all at once. Your for loop currently immediately processes them all, and then the callback is called, without really waiting for the response. – Cody G Dec 31 '17 at 04:56
  • 1
    You need something like this question/answer (https://stackoverflow.com/q/10004112/772035) to wait for all the async callbacks to be done before calling `callback(spots);`. – Paul Dec 31 '17 at 04:56

2 Answers2

2

As stated in the comments, my setDistances function was using callback before there were any responses. Thanks to Paulpro for clearing up the console.log confusion i was having. Heres how i went about fixing my problem:

I removed the for loop that made requests via the getDistanceMatrix and replaced it with a self-calling function call, along with a conditional statement & a count variable to keep track of each individual request, which also invoked the callback when all the requests were completed. Code below:

(resp, status) => {
        spots[this.count].distanceFrom = (resp.rows[0].elements[0].distance.value / 1000).toFixed(1);
        if ((this.count + 1) < spots.length) {
          this.count++;
          this.setDistances(spots, callback);
        } else {
          this.count = 0;
          callback(spots);
        }
    });
Snar3
  • 68
  • 1
  • 11
-1

Try to put you callback(spots) call to this place:

...
service.getDistanceMatrix({
  origins: [origin],
  destinations: [destination],
  travelMode: 'DRIVING',
}, (resp, status) => {
  spots[i].distanceFrom = (resp.rows[0].elements[0].distance.value / 1000).toFixed(1);
  callback(spots);
});

The problem is that your callback(..) is executed before maps callback. So spots data is not yet set at the moment of calling callback(spots).

Iaroslav
  • 295
  • 1
  • 10