调用回调函数时未定义Google

时间:2019-03-22 02:32:43

标签: javascript geocoding google-geocoder

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 :(得分:0)

您的ReferenceError(在堆或堆栈中找不到变量)很可能是由于您的Google Maps api尚未完成网页的下载和/或解析。

异步加载外部资源有很多好处,但是像您遇到的依赖项这样的依赖性问题很常见。

在不知道最终产品是什么的情况下,您有几种选择:

  1. 同步加载地图api,从而确保在调用getpc()时可以可靠地假设google对象将在堆中。将<script src="maps.googleapis.com/maps/api/…" async defer> </script>更改为<script src="maps.googleapis.com/maps/api/…"> </script>。正是出于这些原因,Google文档建议删除异步和延迟
  

在加载Maps JavaScript API的脚本代码中,可以省略async属性和callback参数。这将导致在下载API之前,将阻止API的加载。

这可能会减慢页面加载速度。但这意味着您可以在假定API已加载的情况下编写后续脚本标签。

  1. 在script标签中保留异步和延迟属性,但不要从您自己的脚本中调用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

  2. 使用XMLHttpRequest手动下载库,并通过向XMLHttpRequest.onreadystatechange方法提供回调来执行任何后续例程。 MDN handling onreadystatechange

  3. (不推荐),将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>