简体   繁体   中英

How to wait BingMaps to be loaded in Aurelia

I am trying to use BingMaps in an Aurelia SPA. What I've done is to add BingMaps script tag to the Head section of the Index page. like this:

<head>
    <meta charset="utf-8">
    <script type='text/javascript' src='http://www.bing.com/api/maps/mapcontrol?branch=release'></script>
</head>

Then I have a Map template and Map controller like this:

map.html

<template>
    <div id='mainMap' style='width: 100vw; height: 100vh;'></div>
</template>

map.ts

export class Map
{
    map:Microsoft.Maps.Map;

    attached(){
        this.map = new Microsoft.Maps.Map('#mainMap', {credentials: myKey});
        this.map.setView({center: new Microsoft.Maps.Location(45.093,14.114), zoom:15});
    }
} 

Now, I'm using Aurelia Typescript WebPack Skeleton for my application. If I Run the application and click the Map menu link I created all works correctly and the map i shown. But if I pres Refresh in the browser Aurelia throws an exception:

Unhandled rejection TypeError: Cannot read property 'prototype' of null at k ( https://www.bing.com/mapspreview/sdk/mapcontrol?branch=release:11:7096 ) at h ( https://www.bing.com/mapspreview/sdk/mapcontrol?branch=release:11:6285 ) at e ( https://www.bing.com/mapspreview/sdk/mapcontrol?branch=release:11:1106 ) at tl [as instance] ( https://www.bing.com/mapspreview/sdk/mapcontrol?branch=release:11:161 ) at h ( https://www.bing.com/mapspreview/sdk/mapcontrol?branch=release:11:6042 ) at e ( https://www.bing.com/mapspreview/sdk/mapcontrol?branch=release:11:1106 ) at tl [as instance] ( https://www.bing.com/mapspreview/sdk/mapcontrol?branch=release:11:161 ) at new Microsoft.Maps.Map ( https://www.bing.com/mapspreview/sdk/mapcontrol?branch=release:13:4304 ) at Map.attached ( http://localhost:9000/app.bundle.js:28421:20 ) at Controller.attached

As like the Map script has not been loaded before the Attached method in the Map controller is run. How can I tell Aurelia to wait for the maps script to be loaded before running the Attached method?

You have two options. The first is to add a callback parameter to the map script URL and pass in the name of a function to call when the map script has been loaded. For example:

<script type='text/javascript' src='http://www.bing.com/api/maps/mapcontrol?callback=LoadMap' async defer></script>

Note that you don't need to state you want the release branch, that is the default branch the map control loads.

The second option is a bit messier but has helped others who don't want to use the callback method. This method consists of monitoring the Microsoft.Maps namespace and waiting until it is available. This can be done using timeouts. For example:

function LoadMap(){
    if(typeof Microsoft !== undefined && typeof Microsoft.Maps !== undefined){
        //Map API available add your map load code.
    } else {
        setTimeout(LoadMap, 100);
    }
}

well you need to wait for two events, the first is of course the load of the script, and then you need to wait for the microsoft script to load its API, for that purpose exists the callback parameter: I recommend using jquery for first task as it is easily transformed into a promise, ie:

const _BING_MAPS_URL = 'https//www.bing.com/api/maps/mapcontrol?';
const _DEFAULT_CONFIG = $.params({
  key: 'yourkey',
  callback: 'globalScopedCallback'
});

loadBingMaps() {
  const callbackInvoked = new Promise((resolve) => {
     window.globalScopedCallback = resolve;
  });
  const scriptLoaded = new Promise((resolve, reject) => {
    $.getScript(_BING_MAPS_URL + _DEFAULT_CONFIG).done(resolve).fail(reject);
  });
  // You can add here more promises loading modules, and anything you need.
  return Promise.all([callbackInvoked, scriptLoaded]);
}
// Now you are sure everything is loaded
loadBingMaps().then(doYourAwesomeStuff);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM