Итерация поиска Google Maps API. Сначала выполняется поиск «i» раз, затем обратный вызов «i» раз

Я пытаюсь взять массив координат, выполнить поиск поблизости (https://developers.google.com/maps/documentation/javascript/places) для каждого элемента в массиве, а затем добавить каждый набор результатов в отдельный массив результатов (placesOfInterest).

Вместо того, чтобы делать: Search -> Put results to array -> Search -> Push results to array вроде работает Search -> Search -> Search -> Push results to array -> Push results to array но не могу понять почему.

Первоначально я пытался отправить результаты поиска в массив placesOfInterest, но затем перешел на асинхронную версию, потому что думал, что обратный вызов не выполняется из-за некоторой задержки. Я создал функцию superPush на основе 'appendOutput (элемент), который я нашел в этом руководстве https://codeburst.io/асинхронный код-внутри-ан-массив-петля-c5d704006c99, но это все еще не решило проблему.

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);
  })
}

Что я могу сделать? Невозможно не вызывать обратный вызов, но я не могу придумать, как его обойти.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
100
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Один из вариантов — использовать закрытие функции, чтобы предоставить доступ к индексу массива, в котором должны быть сохранены результаты:

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;
    }
  })
}

называя это так:

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

доказательство концепции скрипки

screenshot with infowindow from search "0"

screenshot with infowindow from search "2"

фрагмент кода:

// 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>

Это отлично работает! Спасибо. Я все еще немного смущен тем, почему он сначала выполняет все поиски, а затем все обратные вызовы. И в моем коде срабатывает строка после, выполняющаяся googlePlaces(point) для всех точек (которая предназначалась для фильтрации массива), а тогда — с обратным вызовом. Если вы сможете указать мне на какие-либо ресурсы, которые объясняют, почему это происходит, я был бы бесконечно благодарен.

Chris A 31.05.2019 14:13

Фактически, после ваших изменений он все еще попадает в строки после цикла до, вызывающего обратный вызов 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.info(placesOfInterest); // hits this line before the callback, the array is still empty here

Chris A 31.05.2019 14:48

Служба мест является асинхронной. Все запросы отправляются до того, как начнут возвращаться результаты, и порядок ответов не гарантируется.

geocodezip 31.05.2019 16:03

Ясно... можно ли дождаться, пока они все закончат?

Chris A 31.05.2019 16:08

Подсчитайте запросы и ответы, когда они совпадают (при условии, что ни один из них не терпит неудачу), все они возвращены (обратите внимание, что это необходимо сделать в функции обратного вызова).

geocodezip 31.05.2019 16:11

Извините, я не понимаю... просто у меня есть больше строк после вызова googlePlaces(), и мне нужно подождать, пока googlePlaces() не завершится, прежде чем он продолжит код.

Chris A 31.05.2019 16:17

возможный дубликат Как вернуть ответ на асинхронный вызов?

geocodezip 31.05.2019 16:20

Другие вопросы по теме