感谢安迪乔斯林。我选择了他包装资源操作的想法。资源的服务现在看起来像这样:
.factory('Todo', ['$resource', 'TokenHandler', function($resource, tokenHandler) {
var resource = $resource('http://localhost:port/todos/:id', {
port:":3001",
id:'@id'
}, {
update: {method: 'PUT'}
});
resource = tokenHandler.wrapActions( resource, ["query", "update"] );
return resource;
}])
如您所见,资源首先以通常的方式定义。在我的示例中,这包括一个名为update
. 之后,资源被方法的返回覆盖,该tokenHandler.wrapAction()
方法将资源和一组动作作为参数。
正如您所期望的那样,后一种方法实际上包装了操作以在每个请求中包含身份验证令牌并返回修改后的资源。因此,让我们看一下代码:
.factory('TokenHandler', function() {
var tokenHandler = {};
var token = "none";
tokenHandler.set = function( newToken ) {
token = newToken;
};
tokenHandler.get = function() {
return token;
};
// wrap given actions of a resource to send auth token with every
// request
tokenHandler.wrapActions = function( resource, actions ) {
// copy original resource
var wrappedResource = resource;
for (var i=0; i < actions.length; i++) {
tokenWrapper( wrappedResource, actions[i] );
};
// return modified copy of resource
return wrappedResource;
};
// wraps resource action to send request with auth token
var tokenWrapper = function( resource, action ) {
// copy original action
resource['_' + action] = resource[action];
// create new action wrapping the original and sending token
resource[action] = function( data, success, error){
return resource['_' + action](
angular.extend({}, data || {}, {access_token: tokenHandler.get()}),
success,
error
);
};
};
return tokenHandler;
});
如您所见,该wrapActions()
方法从其参数创建资源的副本,并循环遍历actions
数组以为每个操作调用另一个函数tokenWrapper()
。最后,它返回资源的修改副本。
该tokenWrapper
方法首先创建一个预先存在的资源操作的副本。此副本有一个尾随下划线。就这样query()
变成了_query()
。之后,一个新方法会覆盖原来的query()
方法。正如 Andy Joslin 所建议的,这种新方法包装_query()
了 auth 令牌,以便为通过该操作发送的每个请求提供身份验证令牌。
这种方法的好处是,我们仍然可以使用每个 angularjs 资源(获取、查询、保存等)附带的预定义操作,而无需重新定义它们。在其余代码中(例如在控制器中),我们可以使用默认操作名称。