Javascript 在forEach循环中使用承诺
我对使用Javascript 在forEach循环中使用承诺,javascript,ecmascript-6,promise,es6-promise,Javascript,Ecmascript 6,Promise,Es6 Promise,我对使用Promise还不熟悉,不能完全正确 我试图创建一种情况,如果页面上的某个元素需要,我将加载GoogleMapsAPI脚本。这部分我已经开始工作了,我正在努力解决的是,如果页面上有超过1个元素需要GoogleMapsAPI,那么我只需要加载一次脚本 这是我到目前为止所拥有的 index.html <div class="map" id="map-1" data-module="map" style="height: 100vh;"></div> <div
Promise
还不熟悉,不能完全正确
我试图创建一种情况,如果页面上的某个元素需要,我将加载GoogleMapsAPI脚本。这部分我已经开始工作了,我正在努力解决的是,如果页面上有超过1个元素需要GoogleMapsAPI,那么我只需要加载一次脚本
这是我到目前为止所拥有的
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>
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();
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();
问题在于load()
函数(我想)。我尝试过各种各样的事情,这是我得到的最接近的。似乎代码没有等待并将脚本标记放入4次,或者代码在脚本标记加载之前解析,mygoogle.maps.Map(…)
无法工作
我将非常感激能得到的任何帮助
干杯,
卢克
更新 已解决 新代码感谢@jcubic帮助我最终找到了解决方案 loadGoogleMapsApi.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();
}
}
}
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;
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();
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成为一个静态类,并将
构造函数
代码移动到load()
函数中。然后还将load()
函数更改为不使用async/await,并添加script.onload=resolve
如果使用thisthis.promise=await新承诺((resolve)=>{/code>this.promise将不是承诺,而是承诺解析的值,这就是async/await的工作方式。您使用未定义的(没有要解析的值())因此此.promise
未定义(它始终为false)
编辑您还需要调用此函数。否则,如果在循环中调用,并且在循环完成之前多次执行,您可能还希望在脚本准备就绪时解析承诺:
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;
}
好的,这有点道理,所以我应该删除this.promise=
?@lukehillonline只需删除async/await,您已经有了promise只需返回它。当我删除async/await时,我会将脚本附加到正文中4次。@lukehillonline没有,因为您有if(!this.promise)
@lukehillonline async/wait只需将您的代码包装成承诺,您不需要它,因为您正在该函数中创建承诺。您可以删除mapload
函数/方法,不再需要它。