user3442612
user3442612

Reputation: 1822

Make Google maps callback wait for rest of functions to finish

I am having difficulty with the way google calls its maps api. I have the following calling initMap

<script defer 
src="https://maps.googleapis.com/maps/api/js?key=API_KEY_REMOVED&callback=initMap">
</script>

but inside initMap, the following condition if(getPosition() !== false) { never evaluates to true because init map is done before getPosition() has set its object values.

function initMap() {
    // set new map, assign default properties
    map = new google.maps.Map(document.getElementById('map'), {
        center: { lat, lng }, zoom: 14
    });
    // check if the requested data is usable (lat, lng === numbers) before trying to use it
    if(getPosition() !== false) {
        map.setCenter( getPosition() ); // set latest position as the map center
        addMarker();
        console.log("InitMap ran here");
    }
}

How can I make it so initMap waits until getPosition() has had a chance to wait for other functions to do their thing? Here is my complete script so it makes more sense.

<script>

console.log(formatTime(Date()));

// https://developers.google.com/maps/documentation/javascript/geolocation
var map; var marker;
var lat = 65.025984; var lng = 25.470794; // default map location in case no position response is available
var res_data; var res_longitude; var res_latitude; var res_speed; var res_time; // res = response (data from the ajax call)
var xhr = new XMLHttpRequest();

function getPosition() {
    pos = {
        lat: res_latitude,
        lng: res_longitude,
    };
    return ( isNaN(pos.lat) || isNaN(pos.lng) ) ? false : pos; // return pos only if lat and lng values are numbers
}

function initMap() {
    // set new map, assign default properties
    map = new google.maps.Map(document.getElementById('map'), {
        center: { lat, lng }, zoom: 14
    });
    // check if the requested data is usable (lat, lng === numbers) before trying to use it
    if(getPosition() !== false) {
        map.setCenter( getPosition() ); // set latest position as the map center
        addMarker();
        console.log("InitMap ran here");
    }
}

// place marker on the map
function addMarker() {
    //console.log("Add Marker ran");
    //https://developers.google.com/maps/documentation/javascript/markers
    if(marker){ marker.setMap(null); } // remove visibility of current marker
    marker = new google.maps.Marker({
        position: getPosition(),
        map: map,
        title: formatTime(res_time),
    });
    marker.setMap(map); // set the marker 
}

function getData() {
    xhr.addEventListener("load", reqListener);
    xhr.open("GET", "http://example.com/data.txt");
    xhr.send();
}

function reqListener() {
    // res_data = long, lat, accuracy, speed, time
    //console.log("reqListener: " + xhr.responseText);
    res_data = '[' + xhr.responseText + ']';
    res_data = JSON.parse(res_data);
    res_latitude = res_data[0]; res_longitude = res_data[1]; res_accuracy = res_data[2]; res_speed = res_data[3]; res_time = res_data[4];
    var formatted_time = formatTime(res_time);

    document.getElementById('info').innerHTML = '<span class="info">Lat: ' + res_latitude + '</span><span class="info">Long: ' + res_longitude + '</span><span class="info">Accuracy: ' + res_accuracy + '</span><span class="info">Speed: ' + res_speed + '</span><span class="info">' + formatted_time + '</span>';

    addMarker();
}

function formatTime(time) {
    var t = new Date(time);
    var hours, mins, secs;
    if(t.getHours() < 10) { hours = "0" + t.getHours(); } else { hours = t.getHours(); }
    if(t.getMinutes() < 10) { mins = "0" + t.getMinutes(); } else { mins = t.getMinutes(); }
    if(t.getSeconds() < 10) { secs = "0" + t.getSeconds(); } else { secs = t.getSeconds(); }
    var hms = hours +':'+ mins +':'+ secs;
    return 'Updated: ' + hms;
}

function init() {
    getData();
    setInterval(getData, 5000); 
}

init();

</script>

<script defer 
    src="https://maps.googleapis.com/maps/api/js?key=API_KEY_REMOVED&callback=initMap">
</script>

Upvotes: 1

Views: 1844

Answers (1)

duncan
duncan

Reputation: 31912

Get rid of the callback=initMap from where you load in the Maps API.

Instead make a call to initMap only from where you are then certain everything is loaded. e.g. at the end of reqListener.

function reqListener() {
    res_data = '[' + xhr.responseText + ']';
    res_data = JSON.parse(res_data);
    res_latitude = res_data[0]; res_longitude = res_data[1]; res_accuracy = res_data[2]; res_speed = res_data[3]; res_time = res_data[4];
    var formatted_time = formatTime(res_time);

    document.getElementById('info').innerHTML = '<span class="info">Lat: ' + res_latitude + '</span><span class="info">Long: ' + res_longitude + '</span><span class="info">Accuracy: ' + res_accuracy + '</span><span class="info">Speed: ' + res_speed + '</span><span class="info">' + formatted_time + '</span>';

    initMap();
    addMarker();
}

If you're calling reqListener at repeated intervals and don't want to recreate your map, add some logic to the top of initMap like:

if (map !== null) {
  return;
}

Upvotes: 1

Related Questions