Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I wait for an asynchronously created object to be completely available before invoking a callback?

I'm trying to create a function that will create a new marker. I need to be able to process some of the properties of the new marker in the callback. The problem is that marker is immediately created and can be used to invoke the callback, but some properties are not yet available.

If I wait two seconds before trying to access the properties, it works just fine - this leads me to believe that the object is still asynchronously generating itself after being created.

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Simple markers</title>
    <style>
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
      #map {
        height: 100%;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script>

function initMap() {
  var latLng = new google.maps.LatLng(-25.363, 131.044);

  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 4,
    center: latLng
  });

  function placeMarker(map, latLng, callback, callback2){
        var marker = new google.maps.Marker({
            position: latLng,
            map: map });

        callback(marker);
        callback2(marker);
    }

    placeMarker(map, latLng, function(marker){
        setTimeout( function(){ 
            console.log(marker.Xg.Oa)
        }, 2000);
    }, function(marker){
        console.log(marker.Xg.Oa);
    });

}
    </script>
    <script async defer
        src="https://maps.googleapis.com/maps/api/js?signed_in=true&callback=initMap"></script>
  </body>
</html>

In this example the callback:

setTimeout( function(){ 
    console.log(marker.Xg.Oa)
}, 2000);

yields the correct response. But the callback that doesn't wait shows an undefined error:

function(marker){
    console.log(marker.Xg.Oa);
}

I'm using a the Google Maps Javascript API library here, and messing with the google.maps stuff isn't an option for obvious reasons. I want to pass the entire object to the callback but I need to ensure that the latLng information (marker.Xg.Oa) exists before invoking it. How can I ensure that it's there before invoking the callback?

like image 494
HPierce Avatar asked Oct 20 '15 19:10

HPierce


1 Answers

NB: I have NOT tested this but something along these lines...

var map = //...
var latLng = //...

function placeMarker(map, latLng, callback){

    return new Promise(function(resolve, reject)(){

        getMarker().then(function(marker){
            //The marker is immediately available
            console.log(marker); //me {__gm: Object, ... }

            //Try to get the value we need
            console.log(marker.Xg.Oa); //Uncaught TypeError: Cannot read property 'Oa' of undefined

            //wait two seconds and try again
            setTimeout(function(){ console.log(marker.Xg.Oa) }, 2000); // L {} (this is the expected output)

            while(!marker.Xg.Oa){ //Uncaught TypeError: Cannot read property 'Oa' of undefined
                callback(marker.Xg.Oa);
            }

            resolve(true);
        });
    });

}

function getMarker()
{
    return new Promise(function(resolve, reject){
        var marker = new google.maps.Marker({
            position: latLng,
            map: map 
        });

        resolve(marker);
    });
}
like image 197
An0nC0d3r Avatar answered Oct 31 '22 16:10

An0nC0d3r