AngularJS,如何使用服务捕获 HTTP 数据并将其绑定到我的控制器?
AngularJS, how do I use a service to capture HTTP data and bind it to my controller?
我有一个很好用的 API 调用,但我想在多个控制器上使用它,所以我将它移到了它自己的服务中。我 运行 陷入了一个看似经典的 Scope 问题或对 Angular 摘要周期的误解。
'use strict';
myApp.factory('Stuff',['$http', function ($http) {
var Stuff = {};
Stuff.data = {};
Stuff.api = 'http://localhost:8080/api/';
Stuff.getStuff = function() {
var http_stuff_config = {
method: 'GET',
url: Stuff.api + 'stuff/'
};
$http(http_stuff_config).then(function successCallback(response) {
Stuff.data = (response.data);
console.log(Stuff.data); // Returns populated object.
},function errorCallback(response) {
console.log(response.statusText);
});
};
Stuff.getStuff();
console.log(Stuff.data); // Returns empty object.
return Stuff;
}]);
myApp.controller('appController', ['$scope','Stuff',function($scope,Stuff) {
$scope.stuff = Stuff;
console.log($scope.stuff.data); // Returns empty object.
$scope.stuff.getJobs();
console.log($scope.stuff.data); // Returns empty object.
}]);
这是重要线索。上面的基本输出,按顺序是...
- 空对象(调用方法后在服务中)
- 空对象(调用方法之前在控制器中)
- 空对象(调用方法后在控制器中)
- 填充的对象(在服务的方法执行中)
- 填充的对象(在控制器的方法执行中)
所以在 getStuff() 方法的范围和 Angular 的操作顺序之间的某处,我正在做一些非常愚蠢的事情。提前谢谢你。
记住 $scope.stuff.getJobs()
是异步的
(这意味着您实际上不能在下一行调用 console.log($scope.stuff.data)
并获取数据)
现在,如果您有一个视图,使用 <span ng-bind="stuff.data.property">
之类的东西,您会发现它工作得很好,因为当异步函数完成时,视图将自行更新。 (这是 angular 的一部分)
我建议您不要将结果存储在服务本身中 (Stuff.data)。只需 return getStuff 函数中的数据,然后让 appController 的范围存储数据。
您需要在您的服务上添加 return,否则 promise 将不会 returned 到控制器。仅将 return 存储在您的服务中而不是将结果 return 存储到控制器中并不是好的做法。
这被认为是不好的做法,因为无论何时您更新服务上的数据,每个人都需要向服务应用 $scope.$watch
以查找更新。这在大型应用程序中可能非常昂贵。
最好的idea是return把数据传给调用controller(如果不需要缓存,这个以后再说)让controller通过promise访问service.getthing().then(function(result){});
myApp.factory('Stuff',['$http', function ($http) {
var Stuff = {};
Stuff.data = {};
Stuff.api = 'http://localhost:8080/api/';
Stuff.getStuff = function() {
var http_stuff_config = {
method: 'GET',
url: Stuff.api + 'stuff/'
};
return $http(http_stuff_config).then(function successCallback(response) {
return response.data;
console.log(Stuff.data); // Returns populated object.
},function errorCallback(response) {
console.log(response.statusText);
});
};
Stuff.getStuff();
console.log(Stuff.data); // Returns empty object.
return Stuff;
}]);
myApp.controller('appController', ['$scope','Stuff',function($scope,Stuff) {
$scope.stuff = Stuff;
console.log($scope.stuff.data); // Returns empty object.
$scope.stuff.getJobs().then(function(result) {$scope.stuff = result; console.log(result);});
console.log($scope.stuff.data); // Returns empty object.
}]);
您需要了解,当您 运行 $http 时,它正在发出 AJAX 请求。因此它不会 return 立即得到结果。
因此,如果您尝试使用来自 $scope.stuff.getJobs() 的数据;调用此函数后,您可能什么也得不到。
你应该做的是让你的 Stuff.getJobs() return 一个承诺,并使用 promise.then(你自己的成功处理程序)来正确处理 return编辑回复。
我已经稍微清理了你的代码。以下是从 Yahoo Weather API.
检索数据的代码的 运行ning 示例
您可以在 CODEPEN 上玩它。
html:
<div ng-app="myApp" ng-controller="appController">
<p>{{data}}</p>
</div>
JS:
var myApp = angular.module("myApp", []);
myApp.factory('Stuff',['$http', function ($http) {
var Stuff = {};
Stuff.data = {};
//sample yahoo weather api
Stuff.api = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22nome%2C%20ak%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys';
Stuff.getData = function() {
var http_stuff_config = {
method: 'GET',
url: Stuff.api + 'stuff/'
};
return $http(http_stuff_config);
};
return Stuff;
}]);
myApp.controller('appController', ['$scope','Stuff',function($scope,Stuff) {
$scope.data = "$http service not ran";
var uncompletedAjaxCall = Stuff.getData();
uncompletedAjaxCall.then(
function(responseData){
$scope.data = responseData;
},
function(errorMsg){}
);
}]);
我有一个很好用的 API 调用,但我想在多个控制器上使用它,所以我将它移到了它自己的服务中。我 运行 陷入了一个看似经典的 Scope 问题或对 Angular 摘要周期的误解。
'use strict';
myApp.factory('Stuff',['$http', function ($http) {
var Stuff = {};
Stuff.data = {};
Stuff.api = 'http://localhost:8080/api/';
Stuff.getStuff = function() {
var http_stuff_config = {
method: 'GET',
url: Stuff.api + 'stuff/'
};
$http(http_stuff_config).then(function successCallback(response) {
Stuff.data = (response.data);
console.log(Stuff.data); // Returns populated object.
},function errorCallback(response) {
console.log(response.statusText);
});
};
Stuff.getStuff();
console.log(Stuff.data); // Returns empty object.
return Stuff;
}]);
myApp.controller('appController', ['$scope','Stuff',function($scope,Stuff) {
$scope.stuff = Stuff;
console.log($scope.stuff.data); // Returns empty object.
$scope.stuff.getJobs();
console.log($scope.stuff.data); // Returns empty object.
}]);
这是重要线索。上面的基本输出,按顺序是...
- 空对象(调用方法后在服务中)
- 空对象(调用方法之前在控制器中)
- 空对象(调用方法后在控制器中)
- 填充的对象(在服务的方法执行中)
- 填充的对象(在控制器的方法执行中)
所以在 getStuff() 方法的范围和 Angular 的操作顺序之间的某处,我正在做一些非常愚蠢的事情。提前谢谢你。
记住 $scope.stuff.getJobs()
是异步的
(这意味着您实际上不能在下一行调用 console.log($scope.stuff.data)
并获取数据)
现在,如果您有一个视图,使用 <span ng-bind="stuff.data.property">
之类的东西,您会发现它工作得很好,因为当异步函数完成时,视图将自行更新。 (这是 angular 的一部分)
我建议您不要将结果存储在服务本身中 (Stuff.data)。只需 return getStuff 函数中的数据,然后让 appController 的范围存储数据。
您需要在您的服务上添加 return,否则 promise 将不会 returned 到控制器。仅将 return 存储在您的服务中而不是将结果 return 存储到控制器中并不是好的做法。
这被认为是不好的做法,因为无论何时您更新服务上的数据,每个人都需要向服务应用 $scope.$watch
以查找更新。这在大型应用程序中可能非常昂贵。
最好的idea是return把数据传给调用controller(如果不需要缓存,这个以后再说)让controller通过promise访问service.getthing().then(function(result){});
myApp.factory('Stuff',['$http', function ($http) {
var Stuff = {};
Stuff.data = {};
Stuff.api = 'http://localhost:8080/api/';
Stuff.getStuff = function() {
var http_stuff_config = {
method: 'GET',
url: Stuff.api + 'stuff/'
};
return $http(http_stuff_config).then(function successCallback(response) {
return response.data;
console.log(Stuff.data); // Returns populated object.
},function errorCallback(response) {
console.log(response.statusText);
});
};
Stuff.getStuff();
console.log(Stuff.data); // Returns empty object.
return Stuff;
}]);
myApp.controller('appController', ['$scope','Stuff',function($scope,Stuff) {
$scope.stuff = Stuff;
console.log($scope.stuff.data); // Returns empty object.
$scope.stuff.getJobs().then(function(result) {$scope.stuff = result; console.log(result);});
console.log($scope.stuff.data); // Returns empty object.
}]);
您需要了解,当您 运行 $http 时,它正在发出 AJAX 请求。因此它不会 return 立即得到结果。
因此,如果您尝试使用来自 $scope.stuff.getJobs() 的数据;调用此函数后,您可能什么也得不到。
你应该做的是让你的 Stuff.getJobs() return 一个承诺,并使用 promise.then(你自己的成功处理程序)来正确处理 return编辑回复。
我已经稍微清理了你的代码。以下是从 Yahoo Weather API.
检索数据的代码的 运行ning 示例您可以在 CODEPEN 上玩它。
html:
<div ng-app="myApp" ng-controller="appController">
<p>{{data}}</p>
</div>
JS:
var myApp = angular.module("myApp", []);
myApp.factory('Stuff',['$http', function ($http) {
var Stuff = {};
Stuff.data = {};
//sample yahoo weather api
Stuff.api = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22nome%2C%20ak%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys';
Stuff.getData = function() {
var http_stuff_config = {
method: 'GET',
url: Stuff.api + 'stuff/'
};
return $http(http_stuff_config);
};
return Stuff;
}]);
myApp.controller('appController', ['$scope','Stuff',function($scope,Stuff) {
$scope.data = "$http service not ran";
var uncompletedAjaxCall = Stuff.getData();
uncompletedAjaxCall.then(
function(responseData){
$scope.data = responseData;
},
function(errorMsg){}
);
}]);