【问题标题】:Change the Promise state of a Promise in Promise.all() when an asynchronous event occurs当异步事件发生时,在 Promise.all() 中更改 Promise 的 Promise 状态
【发布时间】:2021-05-15 13:22:42
【问题描述】:

我正在使用谷歌地图 API。我有两个异步事件,库 API 调用和页面用户的位置请求。在geolocate() functiongetCurrentPosition 中,我检索用户的坐标,如果一切正常,此函数返回一个已解决状态的Promises,位置为value。为了加载 API 库,我使用 JSONP 并在 loadGoogleAPI() 中动态添加了一个脚本,当库准备就绪时,将调用回调函数 googleAPILoaded。当上述 2 个异步事件发生时,我必须继续“异步执行”,并且我正在使用 useGoogleMapsApi() function (await Promise.all) 中的并行执行模式。 我的问题是,当我调用 Promise.all 时,Promise.allgoogleAPIStatus 绑定到其初始值 new Promise(()=>{}) 挂起的 Promise。当加载带有 JSONP 的库时,我将变量的值 googleAPIStatus=Promise.resolve() 更改为已解析的 Promise,但 Promise.all 仍然与初始待处理的 Promise 值相关。 这里是代码。我该如何解决?

 let googleAPIStatus = new Promise(()=>{});

  function googleAPILoaded(){
   console.log('loaded');
   googleAPIStatus = Promise.resolve(); 
}

  function useGoogleMapsApi(){
  loadGoogleAPI();//JSONP with a dynamic script
  let [_,posizione]= await Promise.all([googleAPIStatus , geolocate()]); //parallel execution pattern
  //Here if resolved either the Promises
  }

  function loadGoogleAPI(){
      let isLibraryLoaded = document.querySelector("script[src='google-api']"); 
      if(!(typeof google === 'object' && typeof google.maps === 'object')){
         //Add dynamic script that load the library
         let script = document.createElement('script');
         script.type='text/javascript';
         script.src = 'https://maps.googleapis.com/maps/api/js?key=HEREMYKEY&libraries=places&callback=googleAPILoaded';
         script.id  = 'google-api';
         if(!isLibraryLoaded)
            document.body.appendChild(script);
         else
            isLibraryLoaded.parentNode.replaceChild(script,isLibraryLoaded);
      }
  }

【问题讨论】:

    标签: javascript google-maps-api-3 async-await promise es6-promise


    【解决方案1】:

    您可以公开googleAPIStatus Promise 的结算,以便您可以在googleAPILoaded 回调中结算它的状态。

    let resolve, reject;
    let googleAPIStatus = new Promise((_resolve, _reject) => {
      resolve = _resolve;
      reject = _reject;
    });
    
    function googleAPILoaded() {
      console.log('loaded');
      resolve()
    }
    
    setTimeout(googleAPILoaded, 100);
    
    googleAPIStatus.then(() => console.log("resolved"))

    【讨论】:

    • 智能解决方案。这正是我想要的。我已经在我的代码上对其进行了测试,它可以完成这项工作。我不明白谁对我的问题投了反对票。此外,我无法插入最小的可执行代码,因为密钥 API 不是免费的。
    【解决方案2】:

    另一个答案建议公开解析器函数,即“延迟模式”,由于其封装性差,因此应尽可能避免使用这种反模式。

    请考虑:“如果每个 API 都支持 Promise,我将如何编写这个?”

    然后通过在 Promise 构造函数 (which is their primary purpose) 中包装您遇到的所有旧版非 Promise API 来创建这个现实,或者更好的是,寻找更新的 API。

    在您的情况下,已经存在等待脚本加载的更简单方法:

    async function loadGoogleAPI() {
      if (typeof google === 'object' && typeof google.maps === 'object') {
        return;
      }
      //Add dynamic script that load the library
      const script = document.body.appendChild(document.createElement('script'));
      script.type = 'text/javascript';
      script.src = 'https://maps.googleapis.com/maps/api/js?key=HEREMYKEY&libraries=places';
      script.id = 'google-api';
      await new Promise(resolve => script.onload = resolve);
    }
      
    (async () => {
      try {
        await loadGoogleAPI();    
        console.log(typeof google.maps);
      } catch(e) {
        console.log(e);
      }
    })();

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-03
      • 2018-02-06
      • 1970-01-01
      • 2018-04-11
      • 2015-07-08
      • 2020-08-06
      • 1970-01-01
      • 2021-04-12
      相关资源
      最近更新 更多