我是AngularJS的新手,我现在的JavaScript知识并不强大,所以当我戴上白色腰带并露出我的无知时,我提前道歉。
我很难将以下控制器重构为服务,主要是为了分离关注点并将逻辑推进堆栈,并让我的控制器再次变瘦。
airBnbClone.controller('SpacesCtrl', ['$http', '$location', function( $http, $location) {
var self = this;
self.spaces = [];
self.currentspace;
self.create = function(space) {
$http.post('http://localhost:3000/api/spaces', space).success(function(data) {
self.spaces.push(data);
self.showSpace(data.space);
});
};
self.getSpaces = function(){
$http.get('http://localhost:3000/api/spaces.json').then(function(response){
self.spaces = response.data.reverse();
});
};
self.showSpace = function(space){
$http.get('http://localhost:3000/api/spaces/' + space.id).then(function(response){
self.currentspace = response.data;
$location.path('/spaces/' + space.id)
});
};
}]);
经过一些重构后,我的代码现在看起来像这样:
airBnbClone.controller('SpacesCtrl', ['$http', '$location', 'spacesService', function( $http, $location, spacesService) {
var self = this;
self.create = function(space) {
spacesService.createSpace(space);
};
self.getSpaces = function(){
spacesService.getSpaces();
};
self.showSpace = function(space){
spacesService.showSpace(space);
};
}])
.service('spacesService', ['$http', '$location', function($http, $location){
var self = this;
self.spaces = [];
self.currentspace;
this.createSpace = function(space){
$http.post('http://localhost:3000/api/spaces', space).success(function(data) {
self.spaces.push(data);
self.showSpace(data.space);
});
}
this.getSpaces = function(){
$http.get('http://localhost:3000/api/spaces.json').then(function(response){
self.spaces = response.data.reverse();
});
};
this.showSpace = function(space){
$http.get('http://localhost:3000/api/spaces/' + space.id).then(function(response){
self.currentspace = response.data;
$location.path('/spaces/' + space.id)
});
};
}]);
在我重构之前,我的代码按预期工作。我的主视图有ng-init='spacescontroller.getSpaces()'
,my ng-controller='SpacesCtrl as spacescontroller'
拉入我的空格列表。当我点击某个特定空间时,它会按预期显示该特定空间。
现在,使用我重构的代码,我的默认视图根本不显示任何内容,当我创建空格时,似乎无法更新控制器中的原始self.spaces
数组。
基本上,我不确定如何将这些方法重构为服务。我的self.spaces
和self.currentspace
对象应该保留在控制器中,还是成为注入服务的属性?在这种情况下,哪个是存储状态的首选方法,为什么?
由于我的代码不再呈现视图,为什么会出现这种情况?如果我的问题非常循环,我会道歉,尽管我咨询了许多不同的消息来源,但我已经开始感到非常困惑了。
答案 0 :(得分:2)
您需要一种方法将GET请求的结果从服务带到控制器。
我将逻辑留在控制器中并将所有HTTP请求移动到服务中。我添加了一个回调函数,当结果准备好让控制器使用结果时,它将触发。
airBnbClone.controller('SpacesCtrl', ['$http', '$location', 'spacesService', function($http, $location, spacesService) {
var self = this;
self.spaces = [];
self.currentspace;
self.create = function(space) {
spacesService.createSpace(space, function(data) {
self.spaces.push(data);
self.showSpace(data.space);
});
};
self.getSpaces = function() {
spacesService.getSpaces(function(spaces) {
self.spaces = spaces;
});
};
self.showSpace = function(space) {
spacesService.showSpace(space, function(currentspace) {
self.currentspace = currentspace;
$location.path('/spaces/' + space.id)
});
};
}])
.service('spacesService', ['$http', function($http) {
var self = this;
this.createSpace = function(space, cb) {
$http.post('http://localhost:3000/api/spaces', space).success(function(data) {
cb(data);
});
}
this.getSpaces = function(cb) {
$http.get('http://localhost:3000/api/spaces.json').then(function(response) {
var spaces = response.data.reverse();
cb(spaces);
});
};
this.showSpace = function(space, cb) {
$http.get('http://localhost:3000/api/spaces/' + space.id).then(function(response) {
var currentspace = response.data;
cb(currentspace);
});
};
}]);
答案 1 :(得分:2)
service
服务的使用假定注入了一个保持自己状态的新对象实例。典型的用途是模型类的实例(像MVC模型中的“模型”)。
重构是在正确的轨道上。考虑到spacesService
是一个模型,它可以只分配给控制器(而不是每个模型方法的多个包装器):
this.spacesService = spacesService;
// or any readable property name, e.g.
// this.spaces = spacesService;
所以可以从
的视图中找到它spacescontroller.spacesService.getSpaces()
这里的例外是showSpace
方法。 $location.path
的部分与模型状态无关,并且它执行某些路由这一事实表明它属于控制器,不应从中提取。因此,它可以在控制器中分为spacesService.getSpace(id)
和showSpace
。
答案 2 :(得分:2)
从服务中考虑返回承诺。
app.service('spacesService', function($http) {
this.getSpaces = function(){
var url = 'http://localhost:3000/api/spaces.json';
var promise = $http.get(url)
.then(function(response){
//return for chaining
return response.data.reverse();
});
return promise;
});
});
返回承诺的一个好处是它们保留了错误信息。
在您的控制器中:
airBnbClone.controller('SpacesCtrl', function($http, $location, spacesService) {
var self = this;
self.spaces = [];
self.getSpaces = function() {
var promise = spacesService.getSpaces();
promise.then(function onFulfilled(spaces) {
self.spaces = spaces;
}).catch(function onRejected(response) {
console.log(response.status);
});
};
};
有关使用promises的优势的更多信息,请参阅Why are Callbacks from Promise .then
Methods an Anti-Pattern?.