Google Maps API报错:Cannot access 'AutocompleteDirectionsHandler' before initialization
解决Google Maps Autocomplete API的ReferenceError问题
错误信息
Uncaught (in promise) ReferenceError: Cannot access 'AutocompleteDirectionsHandler' before initialization at window.initMap (traffic.js:25:5)
问题原因
JavaScript中类声明不存在变量提升,你在initMap函数里先尝试实例化AutocompleteDirectionsHandler类,但这个类是在实例化代码之后才定义的,导致执行到实例化语句时,类还未初始化,触发ReferenceError。
修复步骤
- 调整类定义位置:将
AutocompleteDirectionsHandler类的定义移到initMap函数外部,或者在initMap函数内先定义类再进行实例化。 - 修正DOM元素ID不匹配:HTML中模式选择器的ID是
mode,但JS代码里引用的是mode-selector,需要统一ID避免后续功能失效。
修改后的traffic.js代码
let map; // 先定义类,再在initMap中使用 class AutocompleteDirectionsHandler { map; originPlaceId; destinationPlaceId; travelMode; directionsService; directionsRenderer; constructor(map) { this.map = map; this.originPlaceId = ""; this.destinationPlaceId = ""; this.travelMode = google.maps.TravelMode.WALKING; this.directionsService = new google.maps.DirectionsService(); this.directionsRenderer = new google.maps.DirectionsRenderer(); this.directionsRenderer.setMap(map); const originInput = document.getElementById("origin-input"); const destinationInput = document.getElementById("destination-input"); // 修正ID为HTML中的"mode" const modeSelector = document.getElementById("mode"); const originAutocomplete = new google.maps.places.Autocomplete( originInput, { fields: ["place_id"] } ); const destinationAutocomplete = new google.maps.places.Autocomplete( destinationInput, { fields: ["place_id"] } ); this.setupClickListener( "changemode-walking", google.maps.TravelMode.WALKING ); this.setupClickListener( "changemode-transit", google.maps.TravelMode.TRANSIT ); this.setupClickListener( "changemode-driving", google.maps.TravelMode.DRIVING ); this.setupPlaceChangedListener(originAutocomplete, "ORIG"); this.setupPlaceChangedListener(destinationAutocomplete, "DEST"); this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(originInput); this.map.controls[google.maps.ControlPosition.TOP_LEFT].push( destinationInput ); this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(modeSelector); } setupClickListener(id, mode) { const radioButton = document.getElementById(id); radioButton.addEventListener("click", () => { this.travelMode = mode; this.route(); }); } setupPlaceChangedListener(autocomplete, mode) { autocomplete.bindTo("bounds", this.map); autocomplete.addListener("place_changed", () => { const place = autocomplete.getPlace(); if (!place.place_id) { window.alert("Please select an option from the dropdown list."); return; } if (mode === "ORIG") { this.originPlaceId = place.place_id; } else { this.destinationPlaceId = place.place_id; } this.route(); }); } route() { if (!this.originPlaceId || !this.destinationPlaceId) { return; } const me = this; this.directionsService.route( { origin: { placeId: this.originPlaceId }, destination: { placeId: this.destinationPlaceId }, travelMode: this.travelMode, }, (response, status) => { if (status === "OK") { me.directionsRenderer.setDirections(response); } else { window.alert("Directions request failed due to " + status); } } ); } } window.initMap = function() { map = new google.maps.Map(document.getElementById("map"), { zoom: 10, center: { lat: 29.749907, lng: -95.358 }, }); // 现在类已经定义,可以正常实例化 new AutocompleteDirectionsHandler(map); }
额外说明
- 你之前尝试的
async/defer是解决google is not defined的方案,但本次错误是类初始化顺序问题,和API加载时机无关,所以该方案无效。 - 如果需要保留类在
initMap内部,也可以将类定义移到实例化语句之前,效果相同。
内容的提问来源于stack exchange,提问作者Sabrina D
相关产品推荐
相关产品推荐

