Oğuz Can Sertel
Oğuz Can Sertel

Reputation: 759

How to get variables properly with Angularjs promises

I couldn't figure out this problem. My question is why I cannot resolve responses. And I cannot use the responses in my controller. But I get 6 responses as empty. Please open console and push "Get Result" button under the google map. You will see undefined array.

here is plunker

 getGoogleDirection.getData(response,$scope.mymap).then(function(res){
                console.log(res); // **it returns undefined elements**
            });

And here are services.

    App.factory('setData',function($q){
    return {
        getData:function(array){
            var deferred = $q.defer();
            var newArray = [];
            angular.forEach(array,function(firstBlocks,key){
                var dummy = firstBlocks.chunk(9);
                angular.forEach(dummy,function(last,key2){
                    if(key2!=0){
                        dummy[key2].unshift(dummy[key2-1][dummy[key2-1].length-1]);
                    }
                });
                newArray.push(dummy);
            });
            deferred.resolve(newArray);
            return deferred.promise;
        }
    };
}); 
App.factory('getGoogleDirection',function($q){
    return {
        getData:function(array,mymap){
            var distances = [];
            var promises = []
            angular.forEach(array,function(object,key){
                angular.forEach(object,function(array2,key2){
                    promises.push(getDirection(array2));
                });
            });
            function getDirection(array){
                var wayPoints = [];
                var start = array[0];
                var finish = array[array.length-1];
                array.pop();
                array.shift();
                angular.forEach(array,function(item,key){
                    wayPoints.push({
                        location:new google.maps.LatLng(parseFloat(item.lat),parseFloat(item.lng)),
                        stopover:true
                    });
                });
                calcRoute(new google.maps.LatLng(parseFloat(start.lat),parseFloat(start.lng)), wayPoints, new google.maps.LatLng(parseFloat(finish.lat),parseFloat(finish.lng)));
            }
            function calcRoute(start,waypoints,end) {
                var directionsDisplay;
                var directionsService = new google.maps.DirectionsService();
                directionsDisplay = new google.maps.DirectionsRenderer();
                directionsDisplay.setMap(mymap);
                    var request = {
                        origin:start,
                        destination:end,
                        waypoints:waypoints,
                        optimizeWaypoints: false,
                        travelMode: google.maps.TravelMode.DRIVING,
                        avoidHighways:false,
                        avoidTolls:false
                    };
                var deferred = $q.defer();
                return directionsService.route(request, function(response, status) {
                    if (status == google.maps.DirectionsStatus.OK) {
                        directionsDisplay.setDirections(response);
                        deferred.resolve(response);
                    }else{
                        deferred.reject(response);
                        alert('Error');
                    }
                    return deferred.promise;
                });
            }
            return $q.all(promises).then(function(res){
                return res;
            });
        }
    }
});

Upvotes: 2

Views: 470

Answers (2)

ShankarSangoli
ShankarSangoli

Reputation: 69915

When the promise is resolved it provides the resolved data in its callback function. In your code you are not using that.

Change this piece of code

              var dist = [];
              angular.forEach(data, function (d) {
                if (d) dist.push(d);
              });
              console.log(dist);
              return dist;

Take a look here http://plnkr.co/edit/dmlhpWKUxL7CLb1ej8FV?p=preview

Upvotes: 2

Lodewijk Bogaards
Lodewijk Bogaards

Reputation: 19987

$q.all(promises) finishes when all promises are finished, however the promises array does not contain promises at all. What is added to the promises array is the return value of directionsService.route, which is not a promise. When you give $q a non promise to resolve it acts like a promise that is resolved to that same value. For example:

      $q.when(1).then(function(x) {
        alert(x);
      });

Will alert '1', even though 1 is not a promise.

So what you need to do is return a promise that resolves when in the route callback status == google.maps.DirectionsStatus.OK. When your promises resolve properly you can use distances.

However, it is much better to resolve your promises with a distance, so the end result would be something like this:

var result = $q.deferred();
directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
        var distances = [];
        angular.forEach(response.routes[0].legs,function(leg){
              distances.push(leg.distance.value);
          });
        directionsDisplay.setDirections(response); // 
        result.resolve(distances);
    }else{
        result.reject('Google dan veri alımında hata yaşandı');
    }
});
return result.promise;

You can then use it like this: $q.all(promises).then(function(allDistances) { ... }, where allDistances is a 2d array of distances, whereas the first index corresponds to the route and the second index to the leg.

Upvotes: 2

Related Questions