app .factory('Geocoder', function ($localStorage, $q, $timeout) { var locations = $localStorage.locations ? angular.fromJson($localStorage.locations) : {}; var queue = []; // Amount of time (in milliseconds) to pause between each trip to the // Geocoding API, which places limits on frequency. var queryPause = 750; /** * executeNext() - execute the next function in the queue. * If a result is returned, fulfill the promise. * If we get an error, reject the promise (with message). * If we receive OVER_QUERY_LIMIT, increase interval and try again. */ var executeNext = function () { var task = queue[0]; // var geocoder = new google.maps.Geocoder(); // geocoder.geocode({address: task.address}, function (result, status) { $.getJSON("http://maps.googleapis.com/maps/api/geocode/json?address=" + task.address, function (response) { var status = response.status; var result = response.results; if (status === google.maps.GeocoderStatus.OK) { var geometry = angular.toJson(result[0].geometry); geometry = geometry.replace(/"lat":/g, '"latitude":'); geometry = geometry.replace(/"lng":/g, '"longitude":'); var reslt = { geometry: angular.fromJson(geometry), formatted_address: result[0].formatted_address }; queue.shift(); locations[task.address] = reslt; $localStorage.locations = angular.toJson(locations); task.d.resolve(reslt); if (queue.length) { $timeout(executeNext, queryPause); } } else if (status === google.maps.GeocoderStatus.ZERO_RESULTS) { queue.shift(); task.d.reject({ type: 'zero', message: 'Zero results for geocoding address ' + task.address }); } else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) { queryPause += 250; $timeout(executeNext, queryPause); } else if (status === google.maps.GeocoderStatus.REQUEST_DENIED) { queue.shift(); task.d.reject({ type: 'denied', message: 'Request denied for geocoding address ' + task.address }); } else if (status === google.maps.GeocoderStatus.INVALID_REQUEST) { queue.shift(); task.d.reject({ type: 'invalid', message: 'Invalid request for geocoding address ' + task.address }); } }); }; return { latLngForAddress: function (address) { var d = $q.defer(); if (_.has(locations, address)) { $timeout(function () { d.resolve(locations[address]); }); } else { queue.push({ address: address, d: d }); if (queue.length === 1) { executeNext(); } } return d.promise; } }; });