(function(angular) { 'use strict'; var app = angular.module('MyApp', []); app.factory('GeolocationSvc', [ '$q', '$window', function($q, $window) { return function() { var deferred = $q.defer(); if(!$window.navigator) { deferred.reject(new Error('Geolocation is not supported')); } else { $window.navigator.geolocation.getCurrentPosition(function(position) { deferred.resolve({ lat: position.coords.latitude, lng: position.coords.longitude }); }, deferred.reject); } return deferred.promise; }; }]); app.factory('ZipCodeLookupSvc', [ '$q', '$http', 'GeolocationSvc', function($q, $http, GeolocationSvc) { var MAPS_ENDPOINT = 'http://maps.google.com/maps/api/geocode/json?latlng={POSITION}&sensor=false'; return { urlForLatLng: function(lat, lng) { return MAPS_ENDPOINT.replace('{POSITION}', lat + ',' + lng); }, lookupByLatLng: function(lat, lng) { var deferred = $q.defer(); var url = this.urlForLatLng(lat, lng); $http.get(url).success(function(response) { // hacky var zipCode; angular.forEach(response.results, function(result) { if(result.types[0] === 'postal_code') { zipCode = result.address_components[0].short_name; } }); deferred.resolve(zipCode); }).error(deferred.reject); return deferred.promise; }, lookup: function() { var deferred = $q.defer(); var self = this; GeolocationSvc().then(function(position) { deferred.resolve(self.lookupByLatLng(position.lat, position.lng)); }, deferred.reject); return deferred.promise; } }; } ]); app.controller('MainCtrl', ['$scope', 'ZipCodeLookupSvc', function($scope, ZipCodeLookupSvc) { $scope.zipCode = null; $scope.message = 'Finding zip code...'; ZipCodeLookupSvc.lookup().then(function(zipCode) { $scope.zipCode = zipCode; }, function(err) { $scope.message = err; }); }]); })(angular);
<div ng-app="MyApp"> <div ng-controller="MainCtrl"> <div ng-show="zipCode"> <p>{{ zipCode }}</p> </div> <div ng-hide="zipCode"> <p>{{ message }}</p> </div> </div> </div>