我正在建立一个天气应用程序,我首先要获取用户位置,然后提出要求以获取天气。
所以我有GeolocationService
和WeatherService
。我的WeatherService
目前正在调用Geolocation
服务。在发出HTTP请求之前,如何使WeatherService
等待GeolocationService
的结果?
app.factory('GeolocationService',function($q,$window,$rootScope){ return { getLatLon: function(){ var deferred = $q.defer(); if(!window.navigator){ $rootScope.$apply(function(){ deferred.reject(new Error("Geolocation not available")); }); } else { $window.navigator.geolocation.getCurrentPosition(function(position){ $rootScope.$apply(function(){ deferred.resolve(position); }); }, function(error){ $rootScope.$apply(function(){ deferred.reject(error); }); }); } return deferred.promise; } }; }); app.factory("WeatherService", function ($q,$http,$rootScope, GeolocationService) { return { getWeather: function(){ var weather; var loc = new GeolocationService.getLatLon(); var lat= loc.lat || 37.4568202221774, lon= loc.lon || -122.201366838789 ; var units = ''; var url = 'http://api.openweathermap.org/data/2.5/forecast/daily?lat='+lat+'&lon='+lon+'&units='+units+'&callback=JSON_CALLBACK'; $http.jsonp(url) .success(function(data) { weather=data; return weather; }) .error(function(err){ weather=err; return err; }); } }; });
答案 0 :(得分:2)
您只需要在服务中使用承诺,然后将承诺链接起来。对于示例,我有一个user.company_id的用户,如果我想得到公司的名称,我必须等待用户加载。这跟你的情况一样。
这是我的服务:
angular.module('UserService', [])
.factory('UserService', function($q , $http, $rootScope,$timeout) {
var currentUserPromise = null;
var currentCompanyPromise = null;
return {
getCurrentUser: function() {
if (currentUserPromise === null) {
var config = {};
config.cache = true;
config.method = "GET";
config.url = "users/get_current_user";
currentUserPromise = $http(config)
.then(function(response) {
if (typeof response.data === 'object') {
return response.data.user;
} else {
// invalid response
return $q.reject(response.data);
}
}, function(response) {
// something went wrong
return $q.reject(response.data);
});
}
return currentUserPromise;
},
getCurrentCompany: function(company_id) {
if (currentCompanyPromise === null){
var config = {};
var company = {};
company.id = company_id;
config.cache = true;
config.method = "GET";
config.url = "/companies/show";
config.params = company;
currentCompanyPromise = $http(config)
.then(function(response) {
if (typeof response.data === 'object') {
return response.data.company;
} else {
// invalid response
return $q.reject(response.data);
}
}, function(response) {
// something went wrong
return $q.reject(response.data);
});
}
return currentCompanyPromise;
}
};
});
在我的控制器中,我这样使用:
CONTROLLER:
var promiseCurrentUser = UserService.getCurrentUser();
promiseCurrentUser.then(function(user) {
$scope.currentUser = user;
UserService.getCurrentCompany(user.company_id).then(function(company){
$scope.companyName = company.name;
});
});
这个承诺的好处在于它已经解决了一次。
我希望这会对你有所帮助。
答案 1 :(得分:1)
您的GeolocationService
函数getLatLon
正在返回一个承诺。无需使用new
运算符调用它。
您的getWeather
函数应该与以下内容类似:
app.factory("WeatherService", function ($q,$http,$rootScope, GeolocationService) {
return {
getWeather: function(){
var weather;
return GeolocationService.getLatLon().then(
function (loc) {
var lat= loc.lat || 37.4568202221774,
lon= loc.lon || -122.201366838789 ;
var units = '';
var url = 'http://api.openweathermap.org/data/2.5/forecast/daily?lat='+lat+'&lon='+lon+'&units='+units+'&callback=JSON_CALLBACK';
return $http.jsonp(url)
.success(function(data) {
weather=data;
return weather;
})
.error(function(err){
weather=err;
return err;
});
});
}
}
}
在这里,我们首先致电GeolocationService.getLatLon()
以获得承诺。然后我们将我们的处理链接到它。成功函数将通过此处position
获得deferred.resolve(position);
您解决的问题。
此外,您无需将resolve
和reject
包裹在$apply
中。因此,您的GeoLocationService
可以简化为:
if(!window.navigator){
deferred.reject(new Error("Geolocation not available"));
} else {
$window.navigator.geolocation.getCurrentPosition(function(position){
deferred.resolve(position);
}, function(error){
deferred.reject(error);
});
}