-1

I am trying to take an array of coordinates, do a Nearby Search (https://developers.google.com/maps/documentation/javascript/places) for each item in the array, and then add each set of results to a separate array of results (placesOfInterest).

Instead of doing: Search -> Put results to array -> Search -> Push results to array, it seems to be doing Search -> Search -> Search -> Push results to array -> Push results to array but I can't figure out why.

I was originally trying to push the search results to the placesOfInterest array, but then changed to an async version because I thought the callback wasn't getting hit due to some time delay. I created superPush function, based on the 'appendOutput(item) I found on this guide https://codeburst.io/asynchronous-code-inside-an-array-loop-c5d704006c99 but this still didn't fix the problem.

HTML

...
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=<APIKEY>k&libraries=places"></script>
...

JS

var points = [[2.627365,49.215369],[2.760591, 49.647163],[2.952975, 50.057504],[3.344742, 50.280862],[3.768293, 50.451306],[4.21659, 50.534029]]

   for (point of points) {
      googlePlaces(point);
    }



function googlePlaces(point) {
  var latLng = new google.maps.LatLng(point[1],point[0])
  var request = {
    location: latLng,
    radius: '10000'
  };

  service = new google.maps.places.PlacesService(map);
  service.nearbySearch(request, callback);  // hits this code [i] times first...
}

function callback(results, status) {
  if (status == google.maps.places.PlacesServiceStatus.OK) {
    
//results.forEach(result => placesOfInterest.push(result)) // originally tried this way

    results.forEach(result => superPush(result)) // ...then hits this code [i] times

    
   }
}

function superPush(result) {

  fetchData(result).then(function() {
    placesOfInterest.push(result);
  })
}

What can I do? There's no way to not call the callback, but I can't think of a way to get around it.

Community
  • 1
  • 1
Chris A
  • 863
  • 1
  • 10
  • 31

1 Answers1

1

One option is to use function closure to give access to the index of the array that the results need to be saved at:

function googlePlaces(point, index) { // function closure on index
  var latLng = new google.maps.LatLng(point[1], point[0])
  var request = {
    location: latLng,
    radius: '10000'
  };

  service = new google.maps.places.PlacesService(map);
  service.nearbySearch(request, function(results, status) {
    if (status == google.maps.places.PlacesServiceStatus.OK) {
      resultsArray[index] = results;
    }
  })
}

calling it like this:

var i = 0;
for (point of points) {
  googlePlaces(point, i);
  i++;
}

proof of concept fiddle

screenshot with infowindow from search "0"

screenshot with infowindow from search "2"

code snippet:

// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">

var map;
var service;
var infowindow;
var resultsArray = [];
var bounds;

function initMap() {
  bounds = new google.maps.LatLngBounds();
  infowindow = new google.maps.InfoWindow();
  map = new google.maps.Map(
    document.getElementById('map'));

  var points = [
    [2.627365, 49.215369],
    [2.760591, 49.647163],
    [2.952975, 50.057504],
    [3.344742, 50.280862],
    [3.768293, 50.451306],
    [4.21659, 50.534029]
  ]
  var i = 0;
  for (point of points) {
    googlePlaces(point, i);
    i++;
  }
}


function googlePlaces(point, index) {
  var latLng = new google.maps.LatLng(point[1], point[0])
  var request = {
    location: latLng,
    radius: '10000'
  };

  service = new google.maps.places.PlacesService(map);
  service.nearbySearch(request, function(results, status) {
    if (status == google.maps.places.PlacesServiceStatus.OK) {

      resultsArray[index] = results; // ...then hits this code [i] times

      for (var i = 0; i < results.length; i++) {
        var marker = createMarker(results[i], "search " + index);
        bounds.extend(marker.getPosition());
      }
      map.fitBounds(bounds);
    }
  })
}

function createMarker(place, text) {
  var marker = new google.maps.Marker({
    map: map,
    position: place.geometry.location
  });

  google.maps.event.addListener(marker, 'click', function() {
    infowindow.setContent(text + "<br>" + place.name);
    infowindow.open(map, this);
  });
  return marker;
}
html,
body,
#map {
  height: 100%;
  margin: 0;
  padding: 0;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=places&callback=initMap" async defer></script>
geocodezip
  • 158,664
  • 13
  • 220
  • 245
  • That works perfectly! Thank you. I'm still a bit confused about why it does all the searches first and then all of the callbacks. And in my code, the line *after* running `googlePlaces(point)` for all the points is hit (which was intended to filter the array) and *then* it hits the callback. If you are able to point me towards any resources which explain why this is happening I would be eternally grateful. – Chris A May 31 '19 at 12:13
  • In fact, after your changes it still hits the lines after the loop *before* hitting the callback ```function findPlacesWithinRangeOfRoute() { var points = [ [2.627365, 49.215369], [2.760591, 49.647163], [2.952975, 50.057504], [3.344742, 50.280862], [3.768293, 50.451306], [4.21659, 50.534029] ] var i = 0; for (point of points) { googlePlaces(point, i); i++; } console.log(placesOfInterest); // hits this line before the callback, the array is still empty here ``` – Chris A May 31 '19 at 12:48
  • The places service is asynchronous. The request are all sent off before the results start coming back, and the order of the responses is not guaranteed. – geocodezip May 31 '19 at 14:03
  • I see...any way to wait until they are all finished? – Chris A May 31 '19 at 14:08
  • Count the requests and responses, when they match (assuming none fail), they have all returned (note that that needs to be done in the callback function). – geocodezip May 31 '19 at 14:11
  • Sorry, I'm not following... it's just I have more lines after the call to googlePlaces() and I need to wait until googlePlaces() is done before it carries on with the code. – Chris A May 31 '19 at 14:17
  • possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – geocodezip May 31 '19 at 14:20
  • possible duplicate of [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – geocodezip May 31 '19 at 14:21