我有一个资源:
angular.module('mymodule')
.factory('someResource', someResource);
function someResource($resource) {
return $resource('/something', {}, {
find : {method: 'GET', isArray: true, transformResponse: convertFn},
create: {method: 'POST', isArray: true, transformResponse: convertFn},
update: {method: 'PUT', isArray: true, transformResponse: convertFn},
});
function convertFn(){
//...
}
}
是否可以不在每种类型的请求中复制transformResponse?定义一些默认的transformResponse?
可能的解决方案只是通过以编程方式添加属性来修改定义对象,但这样的解决方案看起来很难维护。
angular.module('mymodule')
.factory('someResource', someResource);
function someResource($resource) {
var types = {
find : {method: 'GET', isArray: true},
create: {method: 'POST', isArray: true},
update: {method: 'PUT', isArray: true},
}
//add transform to each, es6
Object.keys(types).forEach(k => types[k].transformResponse = convertFn)
return $resource('/something', {}, types);
function convertFn(){
//...
}
}
修改
对于这个想法,请求georgeawg
另一种方法可能是:为默认值编写包装函数,如:
angular.module('mymodule')
.factory('someResource', someResource);
function someResource($resource) {
var types = {
find : defaults({method: 'GET'}),
create: defaults({method: 'POST', isArray: false}),
update: defaults({method: 'PUT'}),
}
return $resource('/something', {}, types);
function convertFn(){
//...
}
function defaults(opts) {
return Object.assign({
isArray: false,
transformResponse: convertFn
}, opts)
}
}
有一些更清洁的解决方案吗?
答案 0 :(得分:1)
怎么样:
angular.module('mymodule')
.factory('someResource', someResource);
function someResource($resource) {
return $resource('/something', {}, {
find : action('GET'),
create: action('POST'),
update: action('PUT')
});
function action(method) {
return { method: method,
isArray: true,
transformResponse: convertFn
};
}
function convertFn(){
//...
}
}
由于$resource
使用了$http
服务,response interceptor可以转换回复:
app.config(function($httpProvider) {
$httpProvider.interceptors.push(function() {
return {
'request': function(config) {
//
},
'response': function(response) {
if (response.config.url.startsWith("/something") {
response.data = convertFn(response.data);
};
return response;
function convertFn(data) {
//return new data
}
}
});
});
答案 1 :(得分:0)
你看过棱角分明$http interceptors了吗? ngResource将尊重响应拦截器功能。 Here's a post详细说明了用法。
答案 2 :(得分:0)
可以拥有一个非常通用的基础$资源并继承它。
我在SO帖子上找到了我无法找到的答案。如果有人发现它编辑我的帖子来添加它。
以下是我使用的代码:
angular.baseResourceServiceMaker = function(service){
return ['$injector', '$resource', 'TypeService', '$http', '_', 'BackEndpoint', 'Utils',
function($injector, $resource,TypeService, $http, _, BackEndpoint, Utils){
this.restUrl = BackEndpoint+'/rest/';
this.baseName = '';
this.resource = null;
// from angular-resource
var toString= function() {
var value = [];
_.forEach(this, function(e) {
value.push('' + e);
});
return '[' + value.join(', ') + ']';
};
var isObject = function isObject(value) {
// http://jsperf.com/isobject4
return value !== null && typeof value === 'object';
};
var isFile = function(obj) {
return toString.call(obj) === '[object File]';
}
var isFormData = function(obj) {
return toString.call(obj) === '[object FormData]';
}
var isBlob = function(obj) {
return toString.call(obj) === '[object Blob]';
}
this.defaultToJson = function(d) {
return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? angular.toJson(d) : d;
};
this.typeServiceProcessData = function(d){
return TypeService.processData(d);
};
this.typeServiceProcessJsData = function(d){
return TypeService.processJsData(d);
};
this.generateTransformRequestFn = function(mapKeyValues){
return function(data){
var object = {};
_.forEach(_.keys(mapKeyValues), function(key){
Utils.setAttributeValue(object, key, Utils.getAttributeValue(data, mapKeyValues[key]));
});
return object;
}
};
this.addedMethods = {};
// use of resource will be internal, to handle transformation of data
// and so on...
this.getResource = function(){
if(this.resource == null){
var baseResourceUrl = this.restUrl + this.baseName + '/';
var baseResourceMethods = {
'get': {method:'GET', transformResponse:[$http.defaults.transformResponse[0], this.typeServiceProcessData],
url:baseResourceUrl+':id'},
'create': {method:'POST', url:baseResourceUrl, transformRequest:[this.typeServiceProcessJsData, this.defaultToJson]},
'update' : {method:'PUT', transformRequest:[this.typeServiceProcessJsData, this.defaultToJson]},
'search': {method:'GET', isArray:true, transformResponse:[$http.defaults.transformResponse[0], this.typeServiceProcessData],
url:baseResourceUrl+'search/(:search)/:offset/:limit/:order',
params: {offset:0, limit:50, order:"creationDate=asc"}
},
'custom_search': {method:'GET', isArray:true, transformResponse:[$http.defaults.transformResponse[0], this.typeServiceProcessData],
url:baseResourceUrl+':prefix/search/(:search)/:offset/:limit/:order',
params: {search:'pk=gt=0',offset:0, limit:50, order:"creationDate=asc"}
},
'list': {method:'GET', isArray:true, transformResponse:[$http.defaults.transformResponse[0], this.typeServiceProcessData],
url:baseResourceUrl+'search/(pk=gt=0)/0/50/creationDate=asc'
},
'delete': {method:'DELETE'}
};
_.forEach(_.keys(this.addedMethods), function(key){
baseResourceMethods[key] = this.addedMethods[key];
}, this)
this.resource = $resource(baseResourceUrl+':id',
{id:'@pk'}, baseResourceMethods
);
}
return this.resource;
};
this.get = function(id){
this.getResource().get({id:id});
};
this.create = function(data){
this.getResource().create(data);
};
this.update = function(data){
this.getResource().update(data);
};
this.search = function(searchQuery){
this.getResource().search({search:searchQuery});
};
this.searchPaginate = function(searchQuery, offset, limit){
this.getResource().search({search:searchQuery, offset:offset, limit:limit});
};
this['delete'] = function(id){
this.getResource()['delete']({id:id});
};
// Finishes the other injections
$injector.invoke(service, this);
}];
};
关于此代码的一些评论:
使用示例:
.service('ArticleService',angular.baseResourceServiceMaker(['$http', function($http){
this.baseName = 'article';
var baseResourceUrl = this.restUrl + this.baseName + '/';
this.addedMethods.root ={
method:'GET', isArray:true,
transformResponse:[$http.defaults.transformResponse[0], this.typeServiceProcessData],
url:baseResourceUrl+'root'
};
}]))