diff --git a/src/Map/src/Bridge/Google/assets/dist/map_controller.js b/src/Map/src/Bridge/Google/assets/dist/map_controller.js index 13f951a7e60..c7878c5c28f 100644 --- a/src/Map/src/Bridge/Google/assets/dist/map_controller.js +++ b/src/Map/src/Bridge/Google/assets/dist/map_controller.js @@ -120,30 +120,44 @@ default_1.values = { }; let _google; +let _loading = false; +let _loaded = false; +let _onLoadedCallbacks = []; const parser = new DOMParser(); class map_controller extends default_1 { async connect() { - if (!_google) { - _google = { maps: {} }; - let { libraries = [], ...loaderOptions } = this.providerOptionsValue; - const loader = new Loader(loaderOptions); - libraries = ['core', ...libraries.filter((library) => library !== 'core')]; - const librariesImplementations = await Promise.all(libraries.map((library) => loader.importLibrary(library))); - librariesImplementations.map((libraryImplementation, index) => { - if (typeof libraryImplementation !== 'object' || libraryImplementation === null) { - return; - } - const library = libraries[index]; - if (['marker', 'places', 'geometry', 'journeySharing', 'drawing', 'visualization'].includes(library)) { - _google.maps[library] = libraryImplementation; - } - else { - _google.maps = { ..._google.maps, ...libraryImplementation }; - } - }); + const onLoaded = () => super.connect(); + if (_loaded) { + onLoaded(); + return; + } + if (_loading) { + _onLoadedCallbacks.push(onLoaded); + return; } - super.connect(); - this.parser = new DOMParser(); + _loading = true; + _google = { maps: {} }; + let { libraries = [], ...loaderOptions } = this.providerOptionsValue; + const loader = new Loader(loaderOptions); + libraries = ['core', ...libraries.filter((library) => library !== 'core')]; + const librariesImplementations = await Promise.all(libraries.map((library) => loader.importLibrary(library))); + librariesImplementations.map((libraryImplementation, index) => { + if (typeof libraryImplementation !== 'object' || libraryImplementation === null) { + return; + } + const library = libraries[index]; + if (['marker', 'places', 'geometry', 'journeySharing', 'drawing', 'visualization'].includes(library)) { + _google.maps[library] = libraryImplementation; + } + else { + _google.maps = { ..._google.maps, ...libraryImplementation }; + } + }); + _loading = false; + _loaded = true; + onLoaded(); + _onLoadedCallbacks.forEach((callback) => callback()); + _onLoadedCallbacks = []; } centerValueChanged() { if (this.map && this.hasCenterValue && this.centerValue) { diff --git a/src/Map/src/Bridge/Google/assets/src/map_controller.ts b/src/Map/src/Bridge/Google/assets/src/map_controller.ts index 49fbf706eef..94cf80bf23c 100644 --- a/src/Map/src/Bridge/Google/assets/src/map_controller.ts +++ b/src/Map/src/Bridge/Google/assets/src/map_controller.ts @@ -38,6 +38,11 @@ type MapOptions = Pick< let _google: typeof google; +// Loading the Google Maps API is an asynchronous operation, so we need to track the loading state to prevent race conditions. +let _loading = false; +let _loaded = false; +let _onLoadedCallbacks: Array<() => void> = []; + const parser = new DOMParser(); export default class extends AbstractMapController< @@ -64,39 +69,51 @@ export default class extends AbstractMapController< public parser: DOMParser; async connect() { - if (!_google) { - _google = { maps: {} as typeof google.maps }; - - let { libraries = [], ...loaderOptions } = this.providerOptionsValue; - - const loader = new Loader(loaderOptions); - - // We could have used `loader.load()` to correctly load libraries, but this method is deprecated in favor of `loader.importLibrary()`. - // But `loader.importLibrary()` is not a 1-1 replacement for `loader.load()`, we need to re-build the `google.maps` object ourselves, - // see https://github.com/googlemaps/js-api-loader/issues/837 for more information. - libraries = ['core', ...libraries.filter((library) => library !== 'core')]; // Ensure 'core' is loaded first - const librariesImplementations = await Promise.all( - libraries.map((library) => loader.importLibrary(library)) - ); - librariesImplementations.map((libraryImplementation, index) => { - if (typeof libraryImplementation !== 'object' || libraryImplementation === null) { - return; - } + const onLoaded = () => super.connect(); - const library = libraries[index]; + if (_loaded) { + onLoaded(); + return; + } - // The following libraries are in a sub-namespace - if (['marker', 'places', 'geometry', 'journeySharing', 'drawing', 'visualization'].includes(library)) { - // @ts-ignore - _google.maps[library] = libraryImplementation as any; - } else { - _google.maps = { ..._google.maps, ...libraryImplementation }; - } - }); + if (_loading) { + _onLoadedCallbacks.push(onLoaded); + return; } - super.connect(); - this.parser = new DOMParser(); + _loading = true; + _google = { maps: {} as typeof google.maps }; + + let { libraries = [], ...loaderOptions } = this.providerOptionsValue; + + const loader = new Loader(loaderOptions); + + // We could have used `loader.load()` to correctly load libraries, but this method is deprecated in favor of `loader.importLibrary()`. + // But `loader.importLibrary()` is not a 1-1 replacement for `loader.load()`, we need to re-build the `google.maps` object ourselves, + // see https://github.com/googlemaps/js-api-loader/issues/837 for more information. + libraries = ['core', ...libraries.filter((library) => library !== 'core')]; // Ensure 'core' is loaded first + const librariesImplementations = await Promise.all(libraries.map((library) => loader.importLibrary(library))); + librariesImplementations.map((libraryImplementation, index) => { + if (typeof libraryImplementation !== 'object' || libraryImplementation === null) { + return; + } + + const library = libraries[index]; + + // The following libraries are in a sub-namespace + if (['marker', 'places', 'geometry', 'journeySharing', 'drawing', 'visualization'].includes(library)) { + // @ts-ignore + _google.maps[library] = libraryImplementation as any; + } else { + _google.maps = { ..._google.maps, ...libraryImplementation }; + } + }); + + _loading = false; + _loaded = true; + onLoaded(); + _onLoadedCallbacks.forEach((callback) => callback()); + _onLoadedCallbacks = []; } public centerValueChanged(): void {