Search code examples
javascriptgoogle-maps-api-3async-awaitpromisees6-promise

Change the Promise state of a Promise in Promise.all() when an asynchronous event occurs


I'm using google Maps Api. I have two asynchronous events, the library API call and the position request for the user of the page. In the geolocate() function with getCurrentPosition I retrieve the coordinates of the user, this function return a Promises in a resolved state if all is ok, whit the position as value. To load the API library I'm using JSONP with a script dynamically added in loadGoogleAPI(), when the library is ready the callback function googleAPILoaded is called. I have to continue the 'asynchronous execution' when the 2 above described asynchronous event occured and I'm using the pattern of the parallel execution in the useGoogleMapsApi() function (await Promise.all). My problem is that when I call Promise.all , Promise.all for the googleAPIStatus binds to the its initial value new Promise(()=>{}) pending Promise. When the library with JSONP is loaded i change with googleAPIStatus=Promise.resolve() ,the value of the variable, to a resolved Promise but Promise.all instead remains related to the initial pending Promise value. Here the code. How could I resolve?

 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);
      }
  }

Solution

  • You can expose settles of googleAPIStatus Promise so you can settle it's state inside googleAPILoaded callback.

    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"))