Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在forEach循环中使用承诺_Javascript_Ecmascript 6_Promise_Es6 Promise - Fatal编程技术网

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次,或者代码在脚本标记加载之前解析,my
google.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
如果使用this
this.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
函数/方法,不再需要它。