AngularJS:使用异步数据初始化服务 [英] AngularJS : Initialize service with asynchronous data
问题描述
我有一个 AngularJS 服务,我想用一些异步数据对其进行初始化.像这样:
I have an AngularJS service that I want to initialize with some asynchronous data. Something like this:
myModule.service('MyService', function($http) {
var myData = null;
$http.get('data.json').success(function (data) {
myData = data;
});
return {
setData: function (data) {
myData = data;
},
doStuff: function () {
return myData.getSomeData();
}
};
});
显然这是行不通的,因为如果在 myData
返回之前尝试调用 doStuff()
,我会得到一个空指针异常.据我从阅读此处 和 这里 我有几个选项,但似乎没有一个很干净(也许我遗漏了什么):
Obviously this won't work because if something tries to call doStuff()
before myData
gets back I will get a null pointer exception. As far as I can tell from reading some of the other questions asked here and here I have a few options, but none of them seem very clean (perhaps I am missing something):
使用run"设置服务
在设置我的应用时,请执行以下操作:
When setting up my app do this:
myApp.run(function ($http, MyService) {
$http.get('data.json').success(function (data) {
MyService.setData(data);
});
});
然后我的服务看起来像这样:
Then my service would look like this:
myModule.service('MyService', function() {
var myData = null;
return {
setData: function (data) {
myData = data;
},
doStuff: function () {
return myData.getSomeData();
}
};
});
这在某些时候是有效的,但是如果异步数据碰巧花费的时间比初始化所有内容所需的时间长,我在调用 doStuff()
This works some of the time but if the asynchronous data happens to take longer than it takes for everything to get initialized I get a null pointer exception when I call doStuff()
使用承诺对象
这可能会奏效.唯一的缺点是我调用 MyService 的所有地方我都必须知道 doStuff() 返回一个承诺,并且所有代码都必须让我们 then
与承诺进行交互.我宁愿等到 myData 恢复后再加载我的应用程序.
This would probably work. The only downside it everywhere I call MyService I will have to know that doStuff() returns a promise and all the code will have to us then
to interact with the promise. I would rather just wait until myData is back before loading the my application.
手动引导
angular.element(document).ready(function() {
$.getJSON("data.json", function (data) {
// can't initialize the data here because the service doesn't exist yet
angular.bootstrap(document);
// too late to initialize here because something may have already
// tried to call doStuff() and would have got a null pointer exception
});
});
全局 Javascript 变量我可以将我的 JSON 直接发送到全局 Javascript 变量:
Global Javascript Var I could send my JSON directly to a global Javascript variable:
HTML:
<script type="text/javascript" src="data.js"></script>
data.js:
var dataForMyService = {
// myData here
};
然后在初始化MyService
时可用:
myModule.service('MyService', function() {
var myData = dataForMyService;
return {
doStuff: function () {
return myData.getSomeData();
}
};
});
这也可以,但是我有一个全局 javascript 变量,它闻起来很糟糕.
This would work too, but then I have a global javascript variable which smells bad.
这些是我唯一的选择吗?这些选项之一是否比其他选项更好?我知道这是一个很长的问题,但我想表明我已尝试探索所有选项.任何指导将不胜感激.
Are these my only options? Are one of these options better than the others? I know this is a pretty long question, but I wanted to show that I have tried to explore all my options. Any guidance would greatly be appreciated.
推荐答案
你有没有看过$routeProvider.when('/path',{ resolve:{...}
? 它可以使 promise 方法更简洁:
Have you had a look at $routeProvider.when('/path',{ resolve:{...}
? It can make the promise approach a bit cleaner:
在您的服务中公开承诺:
Expose a promise in your service:
app.service('MyService', function($http) {
var myData = null;
var promise = $http.get('data.json').success(function (data) {
myData = data;
});
return {
promise:promise,
setData: function (data) {
myData = data;
},
doStuff: function () {
return myData;//.getSomeData();
}
};
});
将 resolve
添加到您的路由配置中:
Add resolve
to your route config:
app.config(function($routeProvider){
$routeProvider
.when('/',{controller:'MainCtrl',
template:'<div>From MyService:<pre>{{data | json}}</pre></div>',
resolve:{
'MyServiceData':function(MyService){
// MyServiceData will also be injectable in your controller, if you don't want this you could create a new promise with the $q service
return MyService.promise;
}
}})
}):
在解决所有依赖项之前,您的控制器不会被实例化:
Your controller won't get instantiated before all dependencies are resolved:
app.controller('MainCtrl', function($scope,MyService) {
console.log('Promise is now resolved: '+MyService.doStuff().data)
$scope.data = MyService.doStuff();
});
我在 plnkr 做了一个例子:http://plnkr.co/edit/GKg21XH0RwCMEQGUdZKH?p=预览
I've made an example at plnkr: http://plnkr.co/edit/GKg21XH0RwCMEQGUdZKH?p=preview
这篇关于AngularJS:使用异步数据初始化服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!