当前位置:  开发笔记 > 编程语言 > 正文

如何扩展AngularJS资源($ resource)的构造函数?

如何解决《如何扩展AngularJS资源($resource)的构造函数?》经验,为你挑选了2个好方法。

我有一个模型,定义使用$resource,我成功加载.

正如所承诺的,每个加载的实例都是我定义的类的实例.

(以下示例来自Angular文档.在其中,User.get结果是一个对象instanceof User.)

var User = $resource('/user/:userId', {userId:'@id'});

但是,想象每个用户来自这样的电线:

{
  "username": "Bob",
  "preferences": [
    {
      "id": 1,
      "title": "foo",
      "value": false
    }
  ] 
}

我定义了一个PreferencePreference对象添加有价值方法的工厂.但是当用户加载时,这些preferences不是Preference自然的.

我试过这个:

User.prototype.constructor = function(obj) {
  _.extend(this, obj);
  this.items = _.map(this.preferences, function(pref) {
    return new Preference(pref);
  });
  console.log('Our constructor ran'); // never logs anything
}

但它没有任何效果,也从未记录任何东西.

如何使我的Users' preferences数组中的每个项目成为一个实例Preference



1> Andrew Josli..:

$ resource是一个简单的实现,缺少这样的东西.

User.prototype.constructor什么都不做; 与其他库不同,angular不会尝试像面向对象那样行事.这只是javascript.

..但幸运的是,你有承诺和javascript :-).这是你可以做到的一种方式:

function wrapPreferences(user) {
  user.preferences = _.map(user.preferences, function(p) {
    return new Preference(p);
  });
  return user;
}

var get = User.get;
User.get = function() {
  return get.apply(User, arguments).$then(wrapPreferences);
};
var $get = User.prototype.$get;
User.prototype.$get = function() {
  return $get.apply(this, arguments).$then(wrapPreferences);
};

您可以将其抽象为一个装饰任何资源方法的方法:它接受一个对象,一个方法名称数组和一个装饰器函数.

function decorateResource(Resource, methodNames, decorator) {
  _.forEach(methodNames, function(methodName) {
    var method = Resource[methodName];
    Resource[methodName] = function() {
      return method.apply(Resource, arguments).$then(decorator);
    };
    var $method = Resource.prototype[methodName];
    Resource.prototype[methodName] = function() {
      return $method.apply(this, arguments).$then(decorator);
    };
  });
}
decorateResource(User, ['get', 'query'], wrapPreferences);



2> Carl G..:

您可以通过覆盖内置资源操作来转换请求和响应来执行此操作(请参阅文档中的transformRequest和transformResponse.):

var m = angular.module('my-app.resources');
m.factory('User', [
          '$resource',
  function($resource) {

    function transformUserFromServer(user) {
      // Pass Preference directly to map since, in your example, it takes a JSON preference as an argument
      user.preferences = _.map(user.preferences, Preference);
      return user;
    }

    function transformUserForServer(user) {
      // Make a copy so that you don't make your existing object invalid
      // E.g., changes here may invalidate your model for its form, 
      //  resulting in flashes of error messages while the request is 
      //  running and before you transfer to a new page
      var copy = angular.copy(user);
      copy.preferences = _.map(user.preferences, function(pref) {
        // This may be unnecessary in your case, if your Preference model is acceptable in JSON format for your server
        return {
          id: pref.id,
          title: pref.title,
          value: pref.value
        };
      });

      return copy;
    }

    function transformUsersFromServer(users) {
      return _.map(users, transformUserFromServer);
    }

    return $resource('/user/:userId', {
        userId: '@id'
      }, {
        get: {
          method: 'GET',
          transformRequest: [
            angular.fromJson,
            transformUserFromServer
          ]
        },
        query: {
          method: 'GET',
          isArray: true,
          transformRequest: [
            angular.fromJson,
            transformUsersFromServer
          ]
        },
        save: {
          method: 'POST',
          // This may be unnecessary in your case, if your Preference model is acceptable in JSON format for your server
          transformRequest: [
            transformUserForServer,
            angular.toJson
          ],
          // But you'll probably still want to transform the response
          transformResponse: [
            angular.fromJson,
            transformUserFromServer
          ]
        },
        // update is not a built-in $resource method, but we use it so that our URLs are more RESTful
        update: {
          method: 'PUT',
          // Same comments above apply in the update case.
          transformRequest: [
            transformUserForServer,
            angular.toJson
          ],
          transformResponse: [
            angular.fromJson,
            transformUserFromServer
          ]
        }
      }
    );
  };
]);

推荐阅读
农大军乐团_697
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有