英文:
Cannot access 'AutocompleteDirectionsHandler' before initialization for Google Api
问题
我尝试访问Google Maps和Autocomplete API。
这里是我在代码中遇到的错误:
Uncaught (in promise) ReferenceError: Cannot access 'AutocompleteDirectionsHandler' before initialization
at window.initMap (traffic.js:25:5)
这是我的traffic.HTML文件:
<html>
<head>
<title>DREAM MIRROR - Traffic </title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<!-- playground-hide -->
<script>
const process = { env: {} };
process.env.GOOGLE_MAPS_API_KEY =
"MY_API_KEY";
</script>
<!-- playground-hide-end -->
<link rel="stylesheet" type="text/css" href="traffic.css" />
<script type="module" src="traffic.js"></script>
<div class="datetime">
<div class="time"></div>
<div class="date"></div>
</div>
</head>
<style>
a {
color: white;
text-decoration: none;
}
a:hover {
color: #00A0C6;
text-decoration: none;
cursor: pointer;
}
</style>
<a href="../index.html">Back</a>
<body>
<div >
<div id="floating-panel">
<b>Start: </b>
<input type="text" id="origin-input" placeholder="Enter a location" >
<b> <br>
End: </b>
<input type="text" id="destination-input" placeholder="Enter a destination" >
<input type="submit" id="submit">
<select id="mode">
<option value="DRIVING">Driving</option>
<option value="WALKING">Walking</option>
<option value="BICYCLING">Bicycling</option>
<option value="TRANSIT">Transit</option>
</select>
</div>
</div>
<div id="map"></div>
<!-- <div id="warnings-panel"></div> -->
<div id="directions-panel" style="width: 300px; float: right;"></div>
<!--
The `defer` attribute causes the callback to execute after the full HTML
document has been parsed. For non-blocking uses, avoiding race conditions,
and consistent behavior across browsers, consider loading using Promises
with https://www.npmjs.com/package/@googlemaps/js-api-loader.
-->
<script
src="https://maps.googleapis.com/maps/api/js?key=MY_API_KEY&callback=initMap&libraries=places&v=weekly"
defer
></script>
</body>
</html>
这是我的Javascript文件:
let map;
window.initMap = function() {
map = new google.maps.Map(document.getElementById("map"), {
zoom: 10,
center: {
lat: 29.749907,
lng: -95.358
},
});
new AutocompleteDirectionsHandler(map);//<--------ERROR HERE
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");
const modeSelector = document.getElementById("mode-selector");
// Specify just the place data fields that you need.
const originAutocomplete = new google.maps.places.Autocomplete(
originInput,
{ fields: ["place_id"] }
);
// Specify just the place data fields that you need.
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);
}
// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.
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 or !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 = initMap;
我尝试使用异步加载js文件的解决方案,但似乎并没有解决问题。
英文:
I am trying to access the Google Maps and Autocomplete API.
Here is the error I am getting at the
Uncaught (in promise) ReferenceError: Cannot access 'AutocompleteDirectionsHandler' before initialization
at window.initMap (traffic.js:25:5)
Here is my traffic.HTML file
<html>
<head>
<title>DREAM MIRROR - Traffic </title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<!-- playground-hide -->
<script>
const process = { env: {} };
process.env.GOOGLE_MAPS_API_KEY =
"MY_API_KEY";
</script>
<!-- playground-hide-end -->
<link rel="stylesheet" type="text/css" href="traffic.css" />
<script type="module" src="traffic.js"></script>
<div class="datetime">
<div class="time"></div>
<div class="date"></div>
</div>
</head>
<style>
a {
color: white;
text-decoration: none;
}
a:hover {
color: #00A0C6;
text-decoration: none;
cursor: pointer;
}
</style>
<a href="../index.html">Back</a>
<body>
<div >
<div id="floating-panel">
<b>Start: </b>
<input type="text" id="origin-input" placeholder="Enter a location" >
<b> <br>
End: </b>
<input type="text" id="destination-input" placeholder="Enter a destination" >
<input type="submit" id="submit">
<select id="mode">
<option value="DRIVING">Driving</option>
<option value="WALKING">Walking</option>
<option value="BICYCLING">Bicycling</option>
<option value="TRANSIT">Transit</option>
</select>
</div>
</div>
<div id="map"></div>
&nbsp;
<!-- <div id="warnings-panel"></div> -->
<div id="directions-panel" style="width: 300px; float: right;"></div>
<!--
The `defer` attribute causes the callback to execute after the full HTML
document has been parsed. For non-blocking uses, avoiding race conditions,
and consistent behavior across browsers, consider loading using Promises
with https://www.npmjs.com/package/@googlemaps/js-api-loader.
-->
<script
src="https://maps.googleapis.com/maps/api/js?key=MY_API_KEY&callback=initMap&libraries=places&v=weekly"
defer
></script>
</body>
</html>
Here is my Javascript file
let map;
window.initMap = function() {
map = new google.maps.Map(document.getElementById("map"), {
zoom: 10,
center: {
lat: 29.749907,
lng: -95.358
},
});
new AutocompleteDirectionsHandler(map);//<--------ERROR HERE
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");
const modeSelector = document.getElementById("mode-selector");
// Specify just the place data fields that you need.
const originAutocomplete = new google.maps.places.Autocomplete(
originInput,
{ fields: ["place_id"] }
);
// Specify just the place data fields that you need.
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);
}
// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.
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 = initMap;
I tried the solution here
https://stackoverflow.com/questions/55083101/google-maps-uncaught-referenceerror-google-is-not-defined
to load my js file asynchronously before the Google maps script is done being processed by added async defer but it didn't solve it.
I commented where in the code the error is happening and here is a screenshot.
答案1
得分: 0
这里存在语法错误(在 window.initMap=initMap;
之前缺少 }
)。另一个问题是在声明之前使用了 AutocompleteDirectionsHandler
。在类定义之后调用构造函数可以修复这个错误。
代码片段:
let map;
window.initMap = function () {
map = new google.maps.Map(document.getElementById("map"), {
zoom: 10,
center: {
lat: 29.749907,
lng: -95.358
},
});
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");
const modeSelector = document.getElementById("mode-selector");
// Specify just the place data fields that you need.
const originAutocomplete = new google.maps.places.Autocomplete(
originInput, {
fields: ["place_id"]
}
);
// Specify just the place data fields that you need.
const destinationAutocomplete = new google.maps.places.Autocomplete(
destinationInput, {
fields: ["place_id"]
}
);
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);
}
// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.
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);
}
});
}
}
new AutocompleteDirectionsHandler(map); // <--------错误在这里
}
window.initMap = initMap;
希望这对你有所帮助。
英文:
There is a syntax error (missing }
at the end, before the window.initMap=initMap;
). The other problem is you are using the AutocompleteDirectionsHandler
before it is declared. Calling the constructor after the class definition fixes that error.
code snippet:
<!-- begin snippet: js hide: false console: false babel: false -->
<!-- language: lang-js -->
let map;
window.initMap = function() {
map = new google.maps.Map(document.getElementById("map"), {
zoom: 10,
center: {
lat: 29.749907,
lng: -95.358
},
});
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");
const modeSelector = document.getElementById("mode-selector");
// Specify just the place data fields that you need.
const originAutocomplete = new google.maps.places.Autocomplete(
originInput, {
fields: ["place_id"]
}
);
// Specify just the place data fields that you need.
const destinationAutocomplete = new google.maps.places.Autocomplete(
destinationInput, {
fields: ["place_id"]
}
);
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);
}
// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.
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);
}
}
);
}
}
new AutocompleteDirectionsHandler(map); //<--------ERROR HERE
}
window.initMap = initMap;
<!-- language: lang-html -->
<html>
<head>
<title>DREAM MIRROR - Traffic </title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
</head>
<style>
a {
color: white;
text-decoration: none;
}
a:hover {
color: #00A0C6;
text-decoration: none;
cursor: pointer;
}
html,
body {
height: 100%;
width: 100%;
padding: 0;
margins: 0;
}
#map {
height: 80%;
width: 100%;
}
</style>
<a href="../index.html">Back</a>
<body>
<div>
<div id="floating-panel">
<b>Start: </b>
<input type="text" id="origin-input" placeholder="Enter a location">
<b> <br>
End: </b>
<input type="text" id="destination-input" placeholder="Enter a destination">
<input type="submit" id="submit">
<select id="mode">
<option value="DRIVING">Driving</option>
<option value="WALKING">Walking</option>
<option value="BICYCLING">Bicycling</option>
<option value="TRANSIT">Transit</option>
</select>
</div>
</div>
<div id="map"></div>
&nbsp;
<!-- <div id="warnings-panel"></div> -->
<div id="directions-panel" style="width: 300px; float: right;"></div>
<!--
The `defer` attribute causes the callback to execute after the full HTML
document has been parsed. For non-blocking uses, avoiding race conditions,
and consistent behavior across browsers, consider loading using Promises
with https://www.npmjs.com/package/@googlemaps/js-api-loader.
-->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=places&v=weekly" defer></script>
</body>
</html>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论