我需要做的就是下载一个json文件,并在设置路径后将其分配给OCategories
提供程序中的PCategory
。但是我收到$http
不存在的错误。如何将其注入我的提供程序并在setPath
函数内部下载?
var app = angular.module('NSApp',
[
'ui.bootstrap',
'MDItem',
'MDUser',
'MDNotification',
'MDUpload'
]
);
app.config(function(PCategoriesProvider)
{
PCategoriesProvider.setPath('data/csv/categories.json');
});
MDItem /提供者/ category.js
angular.module('MDItem').provider('PCategories',function(){
var OCategories;
var OPath;
return{
setPath: function(d){
OPath = d;
console.log('Path is set. Trying to download categories.');
OCategories = $http.get(oPath);
},
$get : function() {
return {
categories : OCategories
}
}
}
});
答案 0 :(得分:13)
您永远不能将服务实例注入配置函数或提供程序,因为它们尚未配置。存在提供程序以在注入之前配置特定服务。这意味着,某个服务总是有相应的提供商。只是为了澄清,这是使用$location
配置$locationProvider
服务的一个小例子:
angular.module('myModule').config(function ($locationProvider) {
$locationProvider.html5Mode(true);
});
所以这里发生的是,我们配置$location
服务以使用其html5mode。我们通过使用$locationProvider
提供的接口来实现这一点。在执行config()
时,尚未提供任何服务实例,但您可以在实例化之前配置任何服务。
稍后在运行时(最早的时刻是run()
函数),您可以注入服务。注入服务时获得的是其提供者$get()
方法返回的内容。这也意味着,每个提供商都必须有$get()
函数,否则$injector
会抛出错误。
但是,在没有构建提供程序的情况下创建自定义服务会发生什么?如下所示:
angular.module('myModule').factory('myService', function () {
...
});
你只需要关心,因为角度适合你。每当您注册任何类型的服务时(除非它不是提供者),angular将为您设置一个$get()
方法的提供者,因此$injector
能够稍后实例化。
那么如何解决你的问题。如何在实际处于配置短语时使用$http
服务进行异步调用?答案:你做不到。
您可以执行的操作是,只要您的服务被实例化,就会运行$http
调用。因为在您的服务实例化时,您可以注入其他服务(就像您一直这样)。所以你实际上会做这样的事情:
angular.module('myModule').provider('custom', function (otherProvider, otherProvider2) {
// some configuration stuff and interfaces for the outside world
return {
$get: function ($http, injectable2, injectable3) {
$http.get(/*...*/);
}
};
});
现在,您的自定义提供程序返回一个具有$http
依赖关系的服务实例。注入服务后,其所有依赖项也会被注入,这意味着在$get
内您可以访问$http
服务。接下来,您只需拨打电话即可。
要尽快调用此调用,您必须在run()
短语中注入自定义服务,如下所示:
angular.module('myModule').run(function (custom, injectable2) {
/* custom gets instantiated, so its $http call gets invoked */
});
希望这能使事情变得清晰。
答案 1 :(得分:3)
由于所有服务都是角度的单例,因此您可以使用$ http承诺在工厂中存储变量。然后在启动时调用工厂时它将下载json。
然后,您还可以在工厂中公开刷新数据的方法。
我知道这不是你问题的确切答案,但我想我会分享如何做到这一点。
angular.module('MDItem').factory('PCategories', function ($http, PCategoriesPath) {
var service = {
categories: [],
get: function () {
if (angular.isUndefined(PCategoriesPath)) {
throw new Error('PCategoriesPath must be set to get items');
}
$http.get(PCategoriesPath).then(function (response) {
service.categories = response.data;
});
}
};
// Get the categories at startup / or if you like do it later.
service.get();
return service;
});
// Then make sure that PCategoriesPath is created at startup by using const
angular.module('MDItem').const('PCategoriesPath', 'data/csv/categories.json');
angular.module('app').controller('myCtrl', function ($scope, PCategories) {
$scope.categories = PCategories.categories;
// And optionally, use a watch if you would like to do something if the categories are updated via PCategories.get()
$scope.$watch('categories', function (newCategories) {
console.log('Look maa, new categories');
}, true); // Notice the true, which makes angular work when watching an array
})
答案 2 :(得分:2)
你必须在$ get函数中注入$ http,因为这是注入器调用的函数。
但是,要下载类别,最好使用promises:
angular.module('MDItem').provider('PCategories',function(){
var OCategories;
var OPath;
return{
setPath: function(d){
OPath = d;
console.log('Path is set');
},
$get : function($http) {
return {
fetch: function () {
var deferred = $q.defer();
$http.get(oPath).then(function (value) {
deferred.resolve(value);
}
return deferred.promise;
}
}
}
}
});
答案 3 :(得分:0)
我用一种非常简单有效的不同方法实现了我想要的东西。只需在主index.html(NOT PARTIAL)中添加一个虚拟控制器。现在我的所有模块和控制器之间共享数据,所有内容都下载一次。 :)哦,我喜欢AJ。
...
<div ng-controller="initController" hidden></div>
...
initController:
angular.module('NSApp',[]).controller("initController",function($scope, $http, FCategory, FLocation){
$http.get('data/json/categories.json').then(function (response) {
FCategory.categories = response.data;
});
$http.get('data/json/cities.json').then(function (response) {
FLocation.cities = response.data;
});
$http.get('data/json/regions.json').then(function (response) {
FLocation.regions = response.data;
});
});
现在你可以访问它了:
angular.module('MDTest', []).controller("test",function($scope, FCategory, FLocation){
$scope.categories = FCategory.categories;
FCategory工厂
angular.module('MDItem').factory('FCategory', function ($http) {
var service = {
categories: [],
....
};
return service;
});