angularjs $resource 类级回调,或后处理

Posted

技术标签:

【中文标题】angularjs $resource 类级回调,或后处理【英文标题】:angularjs $resource class-level callbacks, or post-processing 【发布时间】:2013-03-28 07:46:22 【问题描述】:

我有一个$resource,它的 API 总是会返回一些需要在进入表示层之前清理的数据。具体来说,它是 .NET 以可爱的'/Date(...)/' 格式返回 Date 对象。

我不想每次调用.query().get() 时都编写回调。是否有某种方法可以通过在更新实例属性的 REST 方法上调用的回调来扩展资源,或者通过添加某种在日期属性更改时触发的 $watch 来扩展资源?基本上这个$resource的每个实例都会发生一些事情。

angular.module('myAppServices', ['ngResource'])
    .factory('Participant', ['$resource', function ($resource) 
        var res = $resource('api/url/participants/:id',  id: '@id' );

        // This obviously doesn't work, but something kinda like this?
        res.prototype.$watch(this.FieldName, function(newVal, oldVal) 
            if (needsCleaning(newVal.fieldName) 
                this.FieldName = cleanupField(newVal);
            
        ;
    );

【问题讨论】:

你可以试试这个。 var participant = $resource('api/url/participants/:id', id: '@id' ); var commonCallback = function() // inside this callback, participant is the populated model, // you can use participant object to do your formatting logic. // Then, if you would like to save the participant object do //participant.$save(); Please not the $ prefixed method names that becomes available to your resources instances. res.query(commonCallback) or res.get(.., commonCallback) 【参考方案1】:

啊哈,我找到了绕过它的方法,并将它留在这里。在 1.1.2 版中,他们添加了对将所有 $http.config 选项传递给 $resource 的支持。当然,我使用的 CDN 没有足够新的 angular-resource.js 版本,但切换 CDN 解决了​​这个问题。

我刚刚使用transformResponse 选项在数据返回时对其进行修改。

angular.module('myAppServices', ['ngResource'])
    .factory('Participant', ['$resource', '$http', function ($resource, $http) 
        var res = $resource('api/url/participants/:id',  id: '@id' , 
        save: 
            method: 'POST',
            transformResponse: $http.defaults.transformResponse.concat([
                function (data, headersGetter) 
                    data.FieldName = yourDateParsingFunction(data.FieldName);

                    return data;
                
            ])
        
    );

我只是将我的转换器添加到 $httpProvider 的 transformResponse 中,它将完成所有的反序列化等操作。

【讨论】:

谢谢,我喜欢$http.defaults.transformResponse.concat 部分。 请注意:您不能在transformResponse内部使用AJAX请求来修改data对象的字段 我必须在工厂函数的末尾添加一个 return 语句才能使其工作。【参考方案2】:

一种简单的方法是覆盖现有的$resource 方法,您希望自己对其进行后处理。有关示例,请参见下面的代码和 cmets。

angular.module('myAppServices', ['ngResource'])
    .factory('Participant', ['$resource', function ($resource) 
        var res = $resource('api/url/participants/:id',  id: '@id' , 
            // create aliases for query and get to be used later
            _query:  method: 'GET', isArray: true ,
            _get:    method: 'GET' 
        );

        // redefine the query method
        res.query = function() 
            // call the original query method via the _query alias, chaining $then to facilitate
            // processing the data
            res._query.apply(null, arguments).$then(function(res) 
                var data = res.data;
                // do any processing you need to do with data here
                return data;
            );
        ;

        // redefine the  method
        res.get = function() 
            // call the original get method via the _get alias, chaining $then to facilitate
            // processing the data
            res._get.apply(null, arguments).$then(function(res) 
                var data = res.data;
                // do any processing you need to do with data here
                return data;
            );
        ;

        return res;
    );

您可以通过Participant.query()Participant.get() 在代码中使用Participant 的相同方式使用它。您在链接的 $then 处理程序中返回的数据将用于解析 $resource 返回的承诺。

【讨论】:

感谢您的回答。我不是 100% 确定,但我认为 transformResponse 可能是更简单的方法。 @c0bra,当你需要访问transformResponse中无法访问的变量时,Intelekshual 的方式很有用 此解决方案的另一个优点是我们可以重用 $resources 中的默认方法来创建我们的自定义方法,然后轻松转换响应【参考方案3】:

我的做法是在模块中添加服务:

angular.module('keeniolab', ['ngResource']).
factory('KeenIO',function ($resource) 
    // factory implementation
).service('KeenModel', function (KeenIO) 
    var KeenSession = function () 
        this.data = ;
    ;

    KeenSession.prototype.fetch = function (query) 
        var self = this;

        KeenIO.get(query, function (result) 
            self.data = result;
        );
    ;

    return new KeenSession();
);

现在您可以简单地监控集合:

$scope.$watchCollection(function () 
    return KeenModel.data;
,
function (value) 
    // code here
);

Keen.IO Resource Factory with Service Model

【讨论】:

以上是关于angularjs $resource 类级回调,或后处理的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS 中的 401 未经授权的错误处理

AngularJS:具有嵌套资源的 $resource

AngularJS:使用 $resource 上传文件(解决方案)

了解 AngularJS 的 $resource

AngularJS $resource GET 中的多个参数

AngularJS - 将 REST 搜索端点映射到 $resource