Google не определяется, когда вызывается функция обратного вызова - PullRequest
0 голосов
/ 22 марта 2019
function initMap() {

            var map = new google.maps.Map(document.getElementById('map'), {
              ..........
            var markers = locations.map(function(location, i) {
              return new google.maps.Marker({
                position: location,
                label: labels[i % labels.length]
              });
            });

            // Add a marker clusterer to manage the markers.
            var markerCluster = new MarkerClusterer(map, markers,
                {imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'});
        }


 //Store LatLng of PostalCode
    var locations = [];

function getLatLng(zipcode, callback) 
{
    var geocoder = new google.maps.Geocoder();
    var address = zipcode;
    geocoder.geocode({ 'address': address }, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            var latitude = results[0].geometry.location.lat();
            var longitude = results[0].geometry.location.lng();
            callback({lat: latitude, lng: longitude });
        } else {
            alert("Request failed.")
        }
    });
}

function getpc(postalcode) {

    getLatLng(postalcode, function (data) {
        locations.push({
            lat : data.lat,
            lng : data.lng
        });
        console.log("lat = " + data.lat + " and lng = " + data.lng);
    });   

}

getpc("640632");

Когда я попытался вызвать функцию getpc (), он вернул Google не определен.Однако, если я попытался удалить его, ошибка не возникает.Я ищу множество способов решить эту проблему, но ни один из них не сработал.Ценю любую помощь.

Это ошибка, отображаемая в console.log:

Uncaught ReferenceError: google is not defined
    at getLatLng (GoogleMapTest.aspx:73)
    at getpc (GoogleMapTest.aspx:88)
    at GoogleMapTest.aspx:98

1 Ответ

0 голосов
/ 22 марта 2019

Ваша ошибка ReferenceError (переменная не найдена в куче или в стеке), скорее всего, из-за того, что API-интерфейс ваших карт Google еще не завершил загрузку и / или не проанализировал вашу веб-страницу.

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

Не зная, каков ваш конечный продукт, у вас есть несколько вариантов:

  1. Синхронно загрузить API-карты, таким образом, гарантируя, что при вызове getpc() вы можете с уверенностью предполагать, что объект google будет в куче.Измените <script src="maps.googleapis.com/maps/api/…" async defer> </script> на <script src="maps.googleapis.com/maps/api/…"> </script>.Документы Google предлагают удалить async и defer по этим причинам точно

В теге script, который загружает JavaScript API Карт, можно пропустить атрибут async и параметр callback.Это приведет к блокировке загрузки API, пока API не будет загружен.

Это, вероятно, замедлит загрузку вашей страницы.Но это означает, что вы можете написать последующие теги сценария, предполагая, что API уже загружен.

Сохраните асинхронные и отложенные атрибуты в теге сценария, но вместо вызова getpc из собственного сценария укажите его в качестве аргумента обратного вызова в параметре запроса следующим образом: src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=getpc">. If you need to invoke 2 or more functions after the maps api is loaded you could compose these into one

Вручную загрузите библиотеку, используя XMLHttpRequest, и выполните любые последующие процедуры, передав обратный вызов методу XMLHttpRequest.onreadystatechange. Работа с MDN при изменении состояния

(не рекомендуется) заменить getpc("640632") на setTimeout(getpc.bind(null, '640632'), 4000)

ОБНОВЛЕНИЕ: Похоже, вам нужно, чтобы эти процедуры были упорядочены таким образом, чтобы getpc вызывалось до initMap.Для этого вы можете воспользоваться решением № 3.Ниже приведен пример того, как это будет работать:

let compose = function(fns) {
  return function() {
    while(fns.length) {
      fns.shift()();
    }
  }
};


let initmap = function() {
  console.log('Init Map');
};


let getpc = function(postalCode) {
  console.log(postalCode);
};


// pass an array of functions you want to be invoked in consecutive order
let initializationRoutines = compose([getpc.bind(null, '123'), initmap]); 

// invoke the functions one-by-one like so
initializationRoutines();

// Instead of invoking initializationRoutines, supply that as the callback to the // maps api. 
// ex: 
<script src="https://maps.googleapis.com/maps/api/jskey=YOUR_API_KEY&callback=initializationRoutines"></script>

Последнее замечание: если вы используете это решение, вам нужно будет определить initializationRoutines перед тем, как вставить тег сценария, который загружает API-карты, например, так.

<head>
<script>
// Compose and define your functions HERE.... Before you load the map api
let compose = function(fns) {/** ... **/};
let initmap = function() {/** .... **/};
let getpc = function(postalCode) {/** .... **/};

// pass an array of functions you want to be invoked in consecutive order
let initializationRoutines = compose(/** ARRAY_OF_FUNCTIONS**/); 
</script>
<script src="https://maps.googleapis.com/maps/api/jskey=YOUR_API_KEY&callback=initializationRoutines"></script>
</head>
<body>
</body>
...