Search code examples
angularjsangularjs-service

Issues with returning an object from an angularjs promise


I am basically trying to retrieve the user's current position using the geolocation api and then pass the coordinates as parameters to an angularjs ajax call and return a custom "address" object as follows:

from the used module:

angular.module('geolocationModule', ['ng'])
.factory('geolocationService', ['$http', function geolocationService($http) {
    return {
        geolocationPosition : function(){
            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(function (position) {
                    return $http.post('/bignibou/geolocation/approximateReverse/', {lat: position.coords.latitude, lng: position.coords.longitude})
                    .then(function(formattedAddress){
                        var address = {};
                        address.formattedAddress = formattedAddress;
                        return address;
                    },
                    function(data, status, headers, config){
                        console.log(data);
                        console.log(status);
                    });
                }, errorFn, {
                    timeout : 10000
                });
            }
        }
    };  
}]);

from calling module:

angular.module('searchEngineModule', ['ng', 'geolocationModule'])
.controller('geolocationCtrl', [ '$scope', 'geolocationService', function geolocationCtrl($scope, geolocationService) {
        $scope.init = function(){
            var geolocationAddress ={};
            geolocationAddress = geolocationService.geolocationPosition();
            console.log(geolocationAddress);
        };
}]);

For some reason, my geolocationAddress object is always undefined...

Can anyone please help?

edit 1:

If I use the following async code:

var geolocationAddress ={};
geolocationService.geolocationPosition().then(function(data) {
     geolocationAddress = data;
});
console.log(geolocationAddress);

Here is what I get:

TypeError: Cannot call method 'then' of undefined
    at Object.$scope.init (http://localhost:8080/bignibou/js/custom/searchEngine.js:5:45)
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js:6541:19
    at Object.Scope.$eval (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js:8218:28)
    at pre (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js:13636:15)
    at nodeLinkFn (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js:4568:13)
    at compositeLinkFn (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js:4191:15)
    at publicLinkFn (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js:4096:30)
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js:1042:27
    at Object.Scope.$eval (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js:8218:28)
    at Object.Scope.$apply (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js:8298:23) <body ng-app="searchEngineModule" ng-controller="geolocationCtrl" ng-init="init()" style="" class="ng-scope"> 

edit 2: Taking into account Chandermani's comments and updating to the following sorted the issue:

angular.module('geolocationModule', ['ng'])
.factory('geolocationService', ['$http', '$q', '$rootScope', function geolocationService($http, $q, $rootScope) {

    function geolocationPositionP (){
        var deferred = $q.defer();
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(                   
            function (position) {
                $rootScope.$apply(function(){
                    console.log(position);
                    deferred.resolve(position);
                });
            },
            function(error){
                deferred.reject(error);
            },
            {timeout: 10000, maximumAge: 0});
        }
        return deferred.promise;
    }

    function geolocationAddressP(){
        var deferred = $q.defer();
        var address = {};
        var geolocationPromise = geolocationPositionP();
        geolocationPromise.then(function(position){
            $http.post('/bignibou/geolocation/approximateReverse/', {lat: position.coords.latitude, lng: position.coords.longitude})
            .success(function(formattedAddress){
                address.formattedAddress = formattedAddress;
                address.latitude = position.coords.latitude;
                address.longitude = position.coords.longitude;
                deferred.resolve(address);
            })
            .error(function(data, status, headers, config){
                console.log(data);
                console.log(status);
                deferred.reject(data);
            });
        });
        return deferred.promise;
    }

    return {
        geolocationAddress : function(){
            return geolocationAddressP();
        } 
    };  
}])

Solution

  • This seems to be a async call issue. Can you try

     geolocationService.geolocationPosition().then(function(data) {
         geolocationAddress = data;
    });
    

    Update: The method geolocationPosition needs to return promise or resource object due to async nature of code. Or you can even try callback method

     geolocationPosition : function(){
                var defer=$q.defer();
                if (navigator.geolocation) {
                    navigator.geolocation.getCurrentPosition(function (position) {
                        return $http.post('/bignibou/geolocation/approximateReverse/', {lat: position.coords.latitude, lng: position.coords.longitude})
                        .then(function(formattedAddress){
                            var address = {};
                            address.formattedAddress = formattedAddress;
                            defer.resolve(address);
                        },
                        function(data, status, headers, config){
                            console.log(data);
                            console.log(status);
                            defer.reject(status)
                        });
                    }, errorFn, {
                        timeout : 10000
                    });
                    return defer.promise
                }
    

    Read a bit about $q http://docs.angularjs.org/api/ng.$q