如何正确地将控制器和服务从 AngularJS 转换为使用 ng-resource
Posted
技术标签:
【中文标题】如何正确地将控制器和服务从 AngularJS 转换为使用 ng-resource【英文标题】:How to properly convert controller and service from AngularJS to using ng-resource 【发布时间】:2016-02-26 08:26:09 【问题描述】:我最近才开始学习 ng-resource。我想知道在将我的常规 AngularJS 应用程序转换为使用 ng-resource 的应用程序时,我是否走在正确的轨道上。
这是我的旧 home.js
控制器(不使用 ng-resource):
angular.module("HomeApp", ["BaseApp"])
.controller("MainCtrl", ["$http", "$window", "BaseService", function($http, $window, BaseService)
var self = this;
BaseService.fetch.posts(function()
self.posts = BaseService.posts;
self.cerrorMessages = BaseService.cerrorMessages;
);
self.like = function(id, postType)
BaseService.like(id, postType, function()
self.cerrorMessages = BaseService.cerrorMessages;
);
;
]);
这是我以前的base.js
(BaseService):
angular.module("BaseApp", [])
.factory("BaseService", ["$http", "$window", function($http, $window)
var self = this;
self.posts = [];
self.cerrorMessages = [];
self.accessErrors = function(data)
self.cerrorMessages = [];
for (prop in data)
if (data.hasOwnProperty(prop))
self.cerrorMessages.push(data[prop]);
;
self.fetch =
posts: function(callback)
$http.get('/posts/')
.then(function(response)
self.posts = response.data;
callback();
, function(response)
self.accessErrors(response.data);
callback();
);
;
self.like = function(id, postType, callback)
$http.post("/" + postType + "/" + id + "/like/")
.then(function(response)
angular.forEach(self.posts, function(post, index, obj)
if (post.id == id)
post.usersVoted.push('voted');
post.voted=true;
;
);
, function(response)
self.accessErrors(response.data);
callback();
);
;
return self;
]);
有人告诉我,我可以从使用 ng-resources 中受益匪浅,因为我有一个 RESTful 后端。我尝试将上面的代码转换为开始使用 ng-resource,这就是我现在所拥有的。这是我的resources.js
:
angular.module('PostsResources', ['ngResource'])
.factory('PostsFactory', function($resource)
return $resource('/posts/:postId', postId:'@id' );
);
.factory('PostLikeFactory', function($resource)
return $resource('/posts/:postId/like', postId:'@id' );
);
这是我的控制器 (home.js
):
angular.module("HomePageApp", ["BaseApp", "PostsApp"])
.controller("MainCtrl", ["$http", "$window", "BaseService", "PostsResource", "PostLikeResource", function($http, $window, BaseService, PostsResource, PostLikeResource)
var self = this;
function loadPosts()
self.posts = PostsFactory.query(function(data) ,
function(error)
BaseService.accessErrors(error.data);
self.cerrorMessages = BaseService.cerrorMessages;
);
;
self.like = function likePost()
PostLikeFactory.save(function(data)
angular.forEach(self.posts, function(post, index, obj)
if (post.id == id)
post.usersVoted.push('voted');
post.voted=true;
;
);
, function(error)
BaseService.accessErrors(error.data);
self.cerrorMessages = BaseService.cerrorMessages;
);
这是我的 BaseService (base.js
):
angular.module("BaseApp", [])
.factory("BaseService", ["$http", "$window", function($http, $window)
var self = this;
self.posts = [];
self.cerrorMessages = [];
self.accessErrors = function(data)
self.cerrorMessages = [];
for (prop in data)
if (data.hasOwnProperty(prop))
self.cerrorMessages.push(data[prop]);
;
return self;
]);
我是否在将常规 AngularJS 应用程序转换为使用 ng-resource 的正确轨道上?在我看来,所需的代码量看起来是一样的。提前致谢!
【问题讨论】:
要点是:User = $resource('/user') -> User.get(), User.post, .... 如果每个 url 只使用一种方法 - 有ng-resource 没有多少利润。 【参考方案1】:我同意@Mark 的观点,即您的 API 中可能没有足够的操作来充分利用 $resource,因此收益并没有那么大。但是,对于您现在所拥有的,如果您想使用 $resource,我会这样设置:
angular.module('PostsResources', ['ngResource'])
.factory('Post', function($resource)
return $resource('/posts/:postId', postId:'@id' ,
like:
url: '/posts/:postId/like',
method: 'POST',
params: postId:'@id'
)
);
如果您到达每个端点使用多个操作的位置,我将有一个 Post 和 PostLike 资源,但在您的情况下,这不是必需的。
在您的控制器中,您将能够像这样处理您的帖子:
self.posts = Post.query(null, BaseService.errorHandler(self));
self.like = function(post)
post.$like(function()
angular.forEach(self.posts, function(post, index, obj)
if (post.id == id)
post.usersVoted.push('voted');
post.voted=true;
;
);
, BaseService.errorHandler(self));
;
您可以添加到 BaseService 中的 errorHandler 方法来消除一些重复。它看起来像这样:
self.errorHandler = function(viewModel)
return function(error)
BaseService.accessErrors(error.data);
viewModel.cerrorMessages = BaseService.cerrorMessages;
;
;
【讨论】:
【参考方案2】:一般来说,我只有在拥有完整的 CRUD Web 应用程序时才使用 ng-resource。示例是 CRM 类型的应用程序,您需要在其中创建客户、更新客户、删除客户并显示客户列表。使用 ng-resource 是有意义的,因为它为您“处理”get
、post
、put
和 delete
HTTP 方法。
但是,在您的示例中,您拥有的唯一操作似乎是“喜欢”和“获取帖子列表”。如果您仅将针对每种资源类型使用一种 HTTP 方法,那么我建议您坚持使用 BaseService
的旧方法。
在这件事上我只有 2 美分。
【讨论】:
以上是关于如何正确地将控制器和服务从 AngularJS 转换为使用 ng-resource的主要内容,如果未能解决你的问题,请参考以下文章
Angularjs 如何对 $http 调用进行正确的错误处理?
如何正确地将排序模型从我的控制器发送到 Laravel API 资源集合?