Javascript AngularJS-将控制器重构为服务-了解self/this和scope
我是AngularJS的新手,我现在的JavaScript知识还不太丰富,所以当我系着白腰带暴露我的无知时,我会提前道歉 我很难将下面的控制器重构成一个服务,主要是为了分离关注点,将逻辑进一步向下推,让我的控制器再次变瘦Javascript AngularJS-将控制器重构为服务-了解self/this和scope,javascript,angularjs,Javascript,Angularjs,我是AngularJS的新手,我现在的JavaScript知识还不太丰富,所以当我系着白腰带暴露我的无知时,我会提前道歉 我很难将下面的控制器重构成一个服务,主要是为了分离关注点,将逻辑进一步向下推,让我的控制器再次变瘦 airBnbClone.controller('SpacesCtrl', ['$http', '$location', function( $http, $location) { var self = this; self.spaces = []; self.cur
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='spacescocontroller.getSpaces()'
,其中My ng controller='SpacesCtrl as spacescocontroller'
拉入了我的空间列表。当我点击一个特定的空间时,它会按照预期显示该特定的空间
现在,对于我的重构代码,我的默认视图没有显示任何内容,当我创建一个空间时,它似乎无法更新位于控制器中的原始self.spaces
数组
基本上,我不确定如何将这些方法重构为服务。我的self.spaces
和self.currentspace
对象应该留在控制器中,还是成为注入服务的属性?在这种情况下,存储状态的首选方法是什么,为什么
既然我的代码不再呈现视图,为什么会出现这种情况?我很抱歉,如果我的问题是循环的,我已经在这几天了,尽管咨询了许多不同的来源,我开始感到非常困惑 您需要一种方法将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);
});
};
}]);
您需要一种将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);
});
};
}]);
service
service的使用假定注入了一个保持其自身状态的新对象实例。它的典型用法是模型类的实例(“model”类似于MVC模型)
重构走上了正确的轨道。考虑到spacesService
是一个模型,可以将其分配给控制器(而不是为每个模型的方法分配许多包装器):
因此,可以从具有
spacescontroller.spacesService.getSpaces()
这里的例外是
showSpace
方法。带有$location.path
的部件与模型状态无关,它执行一些路由的事实表明它属于控制器,不应从中提取。因此,它可以在控制器中分离为spaceservice.getSpace(id)
和showSpace
。使用service
service时,假定注入了一个保持其自身状态的新对象实例。它的典型用法是模型类的实例(“model”类似于MVC模型)
重构走上了正确的轨道。考虑到spacesService
是一个模型,可以将其分配给控制器(而不是为每个模型的方法分配许多包装器):
因此,可以从具有
spacescontroller.spacesService.getSpaces()
这里的例外是
showSpace
方法。带有$location.path
的部件与模型状态无关,它执行一些路由的事实表明它属于控制器,不应从中提取。因此,它可以在控制器中分离为spaceservice.getSpace(id)
和showSpace
。考虑从您的服务中返回承诺
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);
});
};
};
有关使用承诺的好处的更多信息,请参见考虑从您的服务中返回承诺
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);
});
};
};
有关使用承诺的好处的更多信息,请参见您的任何服务方法都不会返回任何结果。建议您学习一些有关服务工作原理的教程。您的服务方法都不会返回任何结果。建议您学习一些有关服务工作原理的教程谢谢。关于
getSpaces()
方法,修改我的视图以包含实际的服务名称是否是一种好的做法?这是否违反了德米特定律?@ggwc对此有不止一个答案。这主要取决于模型本身。如果它通过其公共方法所做的一切都应该在视图中可用(就像在您的案例中),那么是的,没有理由不这样做,并且您可以自由地不将它链接到服务名称并给它另一个名称(空格
或模型
)。或者甚至为spacesService
创建一个代理服务,如果它的API在某个时候被修改了,那么您就不必在视图中更改任何内容。谢谢。关于getSpaces()
方法,修改我的视图以包含实际的服务名称是否是一种好的做法?这是否违反了德米特定律?@ggwc对此有不止一个答案。这主要取决于模型本身。如果它通过其公共方法所做的一切都应该在视图中可用(就像在您的案例中),那么是的,没有理由不这样做,并且您可以自由地不将它链接到服务名称并给它另一个名称(空格
或模型
)。或者甚至为spacesService
创建一个代理服务,如果它的API在某个时候被修改了,那么您不必在视图中更改任何内容。