Saras Arya
Saras Arya

Reputation: 3112

How to make this asynchronous call, synchronous

I have an associative array date as key, the value in this case is an array of objects. Now in this object

while (tempDate < endDate) {
    $scope.dates.push(tempDate.format("DD-MM-YYYY"));
    var dailyTrips = response.data[tempDate.format("DD-MM-YYYY")];
    for (var i = 0; i < dailyTrips.length; i++) {
        // console.log(moment(dailyTrips[i].trip.startTime).format("hh:mm a"));
        // console.log(moment(dailyTrips[i].trip.endTime).format("hh:mm a"));
        geocode(dailyTrips, i);      
    }
    tempDate.add(1, 'days');
}
$scope.data = response.data;

var geocode = function(dailyTrips, i) {
    (function() {
        var latlng = {
             lat: dailyTrips[i].trip.source.latitude,
             lng: dailyTrips[i].trip.source.longitude
        };
        console.log(latlng);
        var geocoder = new google.maps.Geocoder;
        geocoder.geocode({
            'location': latlng
        }, function(result, status) {
            if (result[1]) {
                console.log(result[1].address_components[0].long_name+" "+result[1].address_components[2].long_name);
            }
        });
    }(i));
};

Now This code is working but running at completely different times as it's a callback. I wanted to have this all at one time so that I can use it in ng-repeat and show everything nicely. How do I do that? Expected output

Trip StartTime    Trip from 
Trip EndLine      Trip To

EDIT 1: Still not working

 while (tempDate < endDate) {
     $scope.dates.push(tempDate.format("DD-MM-YYYY"));
     var dailyTrips = response.data[tempDate.format("DD-MM-YYYY")];
     var promises = [];
     for (var i = 0; i < dailyTrips.length; i++) {
         promises[i] = geocode(dailyTrips, i);
     }
     $q.all(promises).then(function(result) {
         console.log(result); //line 39
     });
     tempDate.add(1, 'days');
 }
 $scope.data = response.data;

        }, function(error) {
            console.log(error.data);
        });

    var geocode = function(dailyTrips, i) {
    var q = $q.defer();
    var latlng = {
        lat: dailyTrips[i].trip.source.latitude,
        lng: dailyTrips[i].trip.source.longitude
    };
    console.log(latlng);
    var geocoder = new google.maps.Geocoder;
    geocoder.geocode({
        'location': latlng
    }, function(result, status) {
        console.log(status);
        if (status === google.maps.GeocoderStatus.OK) {
            console.log(result[1].address_components[0].long_name + " " + result[1].address_components[2].long_name);
            q.resolve(result[1].address_components[0].long_name + " " + result[1].address_components[2].long_name);
        } else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
            setTimeout(function() {
                geocode(dailyTrips, i);
            }, 500);
        } else {
            q.reject();
        }
    });
    return q.promise;
};

enter image description here

Upvotes: 1

Views: 84

Answers (1)

Simon H
Simon H

Reputation: 21005

You cannot make an async call synchronous, except by blocking your code, which you do no NOT want to do. Instead, I suggest you convert geocode into a promise

var geocode = function(dailyTrips, i) {
    return this.$q((resolve, reject) => {
       ....

and then wait for all the promises to complete

var promises = [];
for (var i = 0; i < dailyTrips.length; i++) {
   promises[i] = geocode(dailyTrips, i);      
}
$q.all(promises).then( function(results) {...} );

Upvotes: 3

Related Questions