链接承诺,或一个承诺触发另一个承诺
我正在构建一个天气应用程序,首先必须获取用户位置,然后提出请求以获取天气。
所以我有一个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; }); } }; });
你只需要在你的服务中使用诺言,然后再履行诺言。 对于示例我有一个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;
}
};
});
并在我的控制器我用这个这样的:
控制器:
var promiseCurrentUser = UserService.getCurrentUser();
promiseCurrentUser.then(function(user) {
$scope.currentUser = user;
UserService.getCurrentCompany(user.company_id).then(function(company){
$scope.companyName = company.name;
});
});
这个承诺很酷的是,它是一次解决。
我希望这能帮到您。
您的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);
。
此外,您不需要在$apply
包装resolve
和reject
。 因此,您的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);
});
}
链接地址: http://www.djcxy.com/p/77687.html