无法在初始化Google API之前访问 ‘AutocompleteDirectionsHandler’。

huangapple go评论76阅读模式
英文:

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

这是我的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 &#39;AutocompleteDirectionsHandler&#39; before initialization
    at window.initMap (traffic.js:25:5)

Here is my traffic.HTML file


&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;DREAM MIRROR - Traffic &lt;/title&gt;
    &lt;script src=&quot;https://polyfill.io/v3/polyfill.min.js?features=default&quot;&gt;&lt;/script&gt;
    &lt;!-- playground-hide --&gt;
    &lt;script&gt;
      const process = { env: {} };
      process.env.GOOGLE_MAPS_API_KEY =
        &quot;MY_API_KEY&quot;;
    &lt;/script&gt;
    &lt;!-- playground-hide-end --&gt;

    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;traffic.css&quot; /&gt;
    &lt;script type=&quot;module&quot; src=&quot;traffic.js&quot;&gt;&lt;/script&gt;

    &lt;div class=&quot;datetime&quot;&gt;
      &lt;div class=&quot;time&quot;&gt;&lt;/div&gt;
      &lt;div class=&quot;date&quot;&gt;&lt;/div&gt;
      
      
    &lt;/div&gt;
  &lt;/head&gt;
  &lt;style&gt;
    a {

      color: white;
      text-decoration: none;
    }

    a:hover {
      color: #00A0C6;
      text-decoration: none;
      cursor: pointer;
    }
  &lt;/style&gt;
  &lt;a href=&quot;../index.html&quot;&gt;Back&lt;/a&gt;
  &lt;body&gt;
    &lt;div &gt;
      &lt;div id=&quot;floating-panel&quot;&gt;
      &lt;b&gt;Start: &lt;/b&gt;
        
        &lt;input type=&quot;text&quot; id=&quot;origin-input&quot;  placeholder=&quot;Enter a location&quot; &gt;

        &lt;b&gt;  &lt;br&gt;
          End: &lt;/b&gt;
        &lt;input type=&quot;text&quot; id=&quot;destination-input&quot;  placeholder=&quot;Enter a destination&quot; &gt;
&lt;input type=&quot;submit&quot; id=&quot;submit&quot;&gt;
        
&lt;select id=&quot;mode&quot;&gt;
  &lt;option value=&quot;DRIVING&quot;&gt;Driving&lt;/option&gt;
  &lt;option value=&quot;WALKING&quot;&gt;Walking&lt;/option&gt;
  &lt;option value=&quot;BICYCLING&quot;&gt;Bicycling&lt;/option&gt;
  &lt;option value=&quot;TRANSIT&quot;&gt;Transit&lt;/option&gt;
&lt;/select&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;div id=&quot;map&quot;&gt;&lt;/div&gt;
    &amp;nbsp;
    &lt;!-- &lt;div id=&quot;warnings-panel&quot;&gt;&lt;/div&gt; --&gt;
    &lt;div id=&quot;directions-panel&quot; style=&quot;width: 300px; float: right;&quot;&gt;&lt;/div&gt;

    &lt;!-- 
      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.
      --&gt;
    &lt;script
      src=&quot;https://maps.googleapis.com/maps/api/js?key=MY_API_KEY&amp;callback=initMap&amp;libraries=places&amp;v=weekly&quot; 
      defer
    &gt;&lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;

Here is my Javascript file

let map;
window.initMap = function() {
    map = new google.maps.Map(document.getElementById(&quot;map&quot;), {
      zoom: 10,
      center: {
        lat: 29.749907,
        lng: -95.358
      },
    });

    new AutocompleteDirectionsHandler(map);//&lt;--------ERROR HERE

    class AutocompleteDirectionsHandler {
      map;
      originPlaceId;
      destinationPlaceId;
      travelMode;
      directionsService;
      directionsRenderer;
      constructor(map) {
        this.map = map;
        this.originPlaceId = &quot;&quot;;
        this.destinationPlaceId = &quot;&quot;;
        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(&quot;origin-input&quot;);
        const destinationInput = document.getElementById(&quot;destination-input&quot;);
        const modeSelector = document.getElementById(&quot;mode-selector&quot;);
        // Specify just the place data fields that you need.
        const originAutocomplete = new google.maps.places.Autocomplete(
          originInput,
          { fields: [&quot;place_id&quot;] }
        );
        // Specify just the place data fields that you need.
        const destinationAutocomplete = new google.maps.places.Autocomplete(
          destinationInput,
          { fields: [&quot;place_id&quot;] }
        );
    
        this.setupClickListener(
          &quot;changemode-walking&quot;,
          google.maps.TravelMode.WALKING
        );
        this.setupClickListener(
          &quot;changemode-transit&quot;,
          google.maps.TravelMode.TRANSIT
        );
        this.setupClickListener(
          &quot;changemode-driving&quot;,
          google.maps.TravelMode.DRIVING
        );
        this.setupPlaceChangedListener(originAutocomplete, &quot;ORIG&quot;);
        this.setupPlaceChangedListener(destinationAutocomplete, &quot;DEST&quot;);
        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(&quot;click&quot;, () =&gt; {
          this.travelMode = mode;
          this.route();
        });
      }
      setupPlaceChangedListener(autocomplete, mode) {
        autocomplete.bindTo(&quot;bounds&quot;, this.map);
        autocomplete.addListener(&quot;place_changed&quot;, () =&gt; {
          const place = autocomplete.getPlace();
    
          if (!place.place_id) {
            window.alert(&quot;Please select an option from the dropdown list.&quot;);
            return;
          }
    
          if (mode === &quot;ORIG&quot;) {
            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) =&gt; {
            if (status === &quot;OK&quot;) {
              me.directionsRenderer.setDirections(response);
            } else {
              window.alert(&quot;Directions request failed due to &quot; + 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.

无法在初始化Google API之前访问 ‘AutocompleteDirectionsHandler’。

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(&quot;map&quot;), {
zoom: 10,
center: {
lat: 29.749907,
lng: -95.358
},
});
class AutocompleteDirectionsHandler {
map;
originPlaceId;
destinationPlaceId;
travelMode;
directionsService;
directionsRenderer;
constructor(map) {
this.map = map;
this.originPlaceId = &quot;&quot;;
this.destinationPlaceId = &quot;&quot;;
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(&quot;origin-input&quot;);
const destinationInput = document.getElementById(&quot;destination-input&quot;);
const modeSelector = document.getElementById(&quot;mode-selector&quot;);
// Specify just the place data fields that you need.
const originAutocomplete = new google.maps.places.Autocomplete(
originInput, {
fields: [&quot;place_id&quot;]
}
);
// Specify just the place data fields that you need.
const destinationAutocomplete = new google.maps.places.Autocomplete(
destinationInput, {
fields: [&quot;place_id&quot;]
}
);
this.setupPlaceChangedListener(originAutocomplete, &quot;ORIG&quot;);
this.setupPlaceChangedListener(destinationAutocomplete, &quot;DEST&quot;);
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(&quot;click&quot;, () =&gt; {
this.travelMode = mode;
this.route();
});
}
setupPlaceChangedListener(autocomplete, mode) {
autocomplete.bindTo(&quot;bounds&quot;, this.map);
autocomplete.addListener(&quot;place_changed&quot;, () =&gt; {
const place = autocomplete.getPlace();
if (!place.place_id) {
window.alert(&quot;Please select an option from the dropdown list.&quot;);
return;
}
if (mode === &quot;ORIG&quot;) {
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) =&gt; {
if (status === &quot;OK&quot;) {
me.directionsRenderer.setDirections(response);
} else {
window.alert(&quot;Directions request failed due to &quot; + status);
}
}
);
}
}
new AutocompleteDirectionsHandler(map); //&lt;--------ERROR HERE
}
window.initMap = initMap;

<!-- language: lang-html -->

&lt;html&gt;
&lt;head&gt;
&lt;title&gt;DREAM MIRROR - Traffic &lt;/title&gt;
&lt;script src=&quot;https://polyfill.io/v3/polyfill.min.js?features=default&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;style&gt;
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%;
}
&lt;/style&gt;
&lt;a href=&quot;../index.html&quot;&gt;Back&lt;/a&gt;
&lt;body&gt;
&lt;div&gt;
&lt;div id=&quot;floating-panel&quot;&gt;
&lt;b&gt;Start: &lt;/b&gt;
&lt;input type=&quot;text&quot; id=&quot;origin-input&quot; placeholder=&quot;Enter a location&quot;&gt;
&lt;b&gt;  &lt;br&gt;
End: &lt;/b&gt;
&lt;input type=&quot;text&quot; id=&quot;destination-input&quot; placeholder=&quot;Enter a destination&quot;&gt;
&lt;input type=&quot;submit&quot; id=&quot;submit&quot;&gt;
&lt;select id=&quot;mode&quot;&gt;
&lt;option value=&quot;DRIVING&quot;&gt;Driving&lt;/option&gt;
&lt;option value=&quot;WALKING&quot;&gt;Walking&lt;/option&gt;
&lt;option value=&quot;BICYCLING&quot;&gt;Bicycling&lt;/option&gt;
&lt;option value=&quot;TRANSIT&quot;&gt;Transit&lt;/option&gt;
&lt;/select&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;map&quot;&gt;&lt;/div&gt;
&amp;nbsp;
&lt;!-- &lt;div id=&quot;warnings-panel&quot;&gt;&lt;/div&gt; --&gt;
&lt;div id=&quot;directions-panel&quot; style=&quot;width: 300px; float: right;&quot;&gt;&lt;/div&gt;
&lt;!-- 
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.
--&gt;
&lt;script src=&quot;https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&amp;callback=initMap&amp;libraries=places&amp;v=weekly&quot; defer&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年3月3日 22:53:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75628583.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定