我的问题是我不知道在HTTP请求的最终回调中需要访问的数据存储位置。在jQuery中,我将执行以下操作
var token = $.get('/some-url', {}, someCallback);
token.oSomeObject = {data: 'some data'};
function someCallback( data, status, token ){
token.oSomeObject.data // 'some data'
}
我使用令牌存储请求的特定数据。
现在,我发现在Angular中实现这一目标的唯一方法是将数据存储在实际配置中:
var config = {
url: '/some-url',
method: 'GET',
oSomeObject: { data: 'some data' }
};
$http(config).success(someCallback);
function someCallback( data, status, headers, config ){
config.oSomeObject.data // 'some data'
}
首先,这可以防止您使用快捷调用($ http.get,$ http.post)。我还发现,将调用包装在特定服务模块中时,这是一种更为麻烦的方法。
还有其他方法吗?
更新以澄清
我可能只是在这里遗漏了一些简单的东西,无法理解如何正确使用Promise API,但是为了确保我们在同一页面上,让我为您提供更多有关此问题的详细信息。
我有2个文件:1)Controller.js 2)AjaxServices.js(所有ajax调用都在此处定义为服务中的方法)。
AjaxServices.js看起来像这样:
app.service('AjaxService', function( $http ){
var self = this;
this.createUser = function( oUser, fSuccessCallback ){
return $http.put('/api/user', {oUser: oUser})
.success(fSuccessCallback);
}
}
Controller.js看起来像这样:
app.controller('MyController', function( $scope, AjaxServices ){
$scope.saveUser = function( oUser ){
var oPromise = AjaxServices.createUser( oUser, $scope.onUserSaved );
oPromise.oUser = oUser // this is how I solve it in jQuery.ajax. The oPromise
// is then sent as the token object in the onUserSaved
// callback
}
$scope.onUserSaved = function( oStatus, status, headers, config ){
oStatus.id // here is the id of the newly created user
// which I want to now hook on to the oUser local object
}
}
使用promise API如何实现同一目标?
最佳答案
更新2.有关更新后的代码的一些注意事项:
您不必将回调传递给服务。这有效地破坏了承诺的目的。让服务发挥作用,而不将其耦合到数据的任何使用者。
app.service('AjaxService', function( $http ){
var self = this;
this.createUser = function( oUser ){
return $http.put('/api/user', {oUser: oUser});
}
}
现在,该服务不再关心回调,这意味着您可以将多个回调附加到同一服务$ http调用。好的,让我们继续服务数据使用者,在这种情况下,它是控制器:
app.controller('MyController', function( $scope, AjaxServices ){
$scope.saveUser = function( oUser ){
var oOriginalPromise = AjaxServices.createUser( oUser );
//lets modify the orginal promise to include our oUser
var oModifiedPromise = oOriginalPromise.then(function(response) {
response.oUser = oUser;
return response;
});
//in the code above we've chained original promise with .then,
//modified response object and returned it for next promise to receive
//at the same time, .then created a new promise
//finally, after modifying our response, we can pass it to the desired callback.
//note, that .success and .error are $http specific promise methods,
//in all other cases use .then(fnSuccess, fnError)
oModifiedPromise.then($scope.onUserSaved);
}
$scope.onUserSaved = function(responseWithUser) {
responseWithUser.oUser;
}
}
当然,它仍然有点尴尬,因为oUser可以保存在控制器的作用域中,并且可以在$ scope.onUserSaved中直接从那里访问。
更新。我会澄清我的答案。您可以在任何范围,任何地方链接承诺。这是服务注入令牌的另一个示例:
myModule.factory('Service', function($http) {
return new function() {
this.getData = function() {
return $http.get(url).then(function(response) {
response.token = myToken;
return response;
}
}
}
});
您甚至可以扩展或包装$ http服务,并在响应上插入令牌,而服务却不知道。
如果您对所有请求都这样做,则也许$ httpInterceptor更合适。了解有关拦截HTTP调用here的更多信息
原始答案
由于
$http
为您提供了承诺,因此您可以将其链接到另一个将注入令牌作为响应的承诺中:myModule.factory('Service', function($http) {
return new function() {
this.getData = function() {
return $http.get(url);
}
}
});
//in controller or other service:
var myToken;
var tokenizedPromise = Service.getData().then(function(response) {
response.token = myToken;
return response;
});
承诺的最终消费者也可以访问令牌