首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在forEach循环中使用允诺

在forEach循环中使用允诺
EN

Stack Overflow用户
提问于 2019-02-14 14:37:08
回答 1查看 129关注 0票数 1

我刚开始使用Promise,不能完全理解这一点。

如果页面上的元素需要,我正在尝试创建一个加载google脚本的情况。这部分我已经开始工作了,我正在挣扎的是,如果页面上有超过一个元素需要google,我只需要加载一次脚本。

这是我到目前为止所拥有的。

index.html

代码语言:javascript
复制
<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>

loadGoogleMapsApi.js

代码语言:javascript
复制
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

代码语言:javascript
复制
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(...)无法工作之前,代码解析。

我能得到的任何帮助都将受到极大的感谢。

干杯卢克。

更新

解决了

新代码多亏了@j立方帮助我终于找到了解决方案。

loadGoogleMapsApi.js

代码语言:javascript
复制
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

代码语言:javascript
复制
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()函数更改为不使用异步/等待和添加script.onload = resolve

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-14 14:40:37

如果您使用这个this.promise = await new Promise((resolve) => { this.promise将不是承诺,而是价值承诺决心,这是异步/等待的工作方式。您是用未定义的(没有值来解析())来解析它的,因此this.promise是未定义的(它始终是假的)。

编辑--您还需要调用this.resolve --否则,如果您在循环中调用它多次,然后在它完成之前执行它,那么您可能也希望在脚本准备就绪时解决这个承诺:

代码语言:javascript
复制
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;
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54692912

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档