gpt4 book ai didi

javascript - 在 forEach 循环中使用 Promise

转载 作者:行者123 更新时间:2023-11-30 11:08:33 25 4
gpt4 key购买 nike

我是 Promise 的新手,不太了解这一点。

我正在尝试创建一种情况,如果页面上的元素需要它,我会加载 google maps API 脚本。这部分我已经开始工作,我正在努力解决的问题是,如果页面上有超过 1 个元素需要 google maps API,我只需要加载一次脚本。

这是我目前所拥有的。

index.html

<div class="map" id="map-1" data-module="map" style="height: 100vh;"></div>

<div class="map" id="map-2" data-module="map" style="height: 100vh;"></div>

<div class="map" id="map-3" data-module="map" style="height: 100vh;"></div>

<div class="map" id="map-4" data-module="map" style="height: 100vh;"></div>

加载GoogleMapsApi.js

export default class LoadGoogleMapsAPI {
constructor() {

this.apiKey = '********';

// set a globally scoped callback if it doesn't already exist
/* eslint no-underscore-dangle: 0 */
if (!window._GoogleMapsApi) {
this.callbackName = '_GoogleMapsApi.mapLoaded';
window._GoogleMapsApi = this;
window._GoogleMapsApi.mapLoaded = this.mapLoaded.bind(this);
}

}

/**
* Load the Google Maps API javascript
*/
async load() {
if (!this.promise) {
this.promise = await new Promise((resolve) => {
this.resolve = resolve;

if (typeof window.google === 'undefined') {
const script = document.createElement('script');
script.src = `//maps.googleapis.com/maps/api/js?key=${window._GoogleMapsApi.apiKey}&callback=${window._GoogleMapsApi.callbackName}`;
script.async = true;
document.body.append(script);
} else {
this.resolve();
}
});
}

return this.promise;
}

/**
* Globally scoped callback for the map loaded
*/
mapLoaded() {
if (this.resolve) {
this.resolve();
}
}
}

map .js

import GoogleMapsApi from '../utils/loadGoogleMapsApi';

export default class MapViewModel {
constructor(module) {

this.module = module;

const gmapApi = new GoogleMapsApi();

gmapApi.load().then(() => {
// safe to start using the API now
new google.maps.Map(this.module, {
center: { lat: 51.5074, lng: -0.1278 },
zoom: 11,
});
// etc.
});
}

static init() {
const instances = document.querySelectorAll('[data-module="map"]');

instances.forEach((module) => {
const options = JSON.parse(module.getAttribute('data-map-settings'));
new MapViewModel(module, options);
});
}
}

MapViewModel.init();

问题出在 load() 函数中(我认为)。我尝试了各种不同的东西,这是我最接近的。似乎代码要么不等待并将脚本标记放入 4 次,要么代码在脚本标记加载之前解析并且我的 google.maps.Map(...) 不起作用.

我将不胜感激任何帮助。

干杯,卢克。


更新

已解决

感谢@jcubic 帮助我最终找到解决方案的新代码。

加载GoogleMapsApi.js

export default class LoadGoogleMapsAPI {
/**
* Load the Google Maps API javascript
*/
static load() {
this.apiKey = '******';

if (!this.promise) {
this.promise = new Promise((resolve) => {

if (typeof window.google === 'undefined') {
const script = document.createElement('script');
script.onload = resolve;
script.src = `//maps.googleapis.com/maps/api/js?key=${this.apiKey}`;
script.async = true;
document.body.append(script);
}
});
}

return this.promise;
}
}

map .js

import GoogleMapsApi from '../utils/loadGoogleMapsApi';

export default class MapViewModel {
constructor(module) {

this.module = module;

GoogleMapsApi.load().then(() => {
// safe to start using the API now
new google.maps.Map(this.module, {
center: { lat: 51.5074, lng: -0.1278 },
zoom: 11,
});
// etc.
});
}

static init() {
const instances = document.querySelectorAll('[data-module="map"]');

instances.forEach((module) => {
const options = JSON.parse(module.getAttribute('data-map-settings'));
new MapViewModel(module, options);
});
}
}

MapViewModel.init();

所以解决方案的两个部分是使 loadGoogleMapsApi.js 成为一个静态类,并将 constructor 代码移动到 load() 函数中。然后还更改 load() 函数以不使用 async/await 并添加 script.onload = resolve

最佳答案

如果你使用这个 this.promise = await new Promise((resolve) => { this.promise 将不是一个 promise 而是 promise resolve 的值,这就是 async/await 的工作方式. 你用 undefined 解析它(resolve() 没有值)所以 this.promise 是 undefined(它总是 false)。

编辑 你还需要调用 this.resolve 否则如果你在一个循环中调用你在它完成之前多次执行它,你可能还想在脚本准备好时解决 promise :

load() {
if (!this.promise) {
this.promise = new Promise((resolve) => {

if (typeof window.google === 'undefined') {
const script = document.createElement('script');
script.onload = resolve;
script.src = `//maps.googleapis.com/maps/api/js?key=${window._GoogleMapsApi.apiKey}&callback=${window._GoogleMapsApi.callbackName}`;
script.async = true;
document.body.append(script);

}
});
}

return this.promise;
}

关于javascript - 在 forEach 循环中使用 Promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54692912/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com