我有一个AngularJS服务,我想用一些异步数据初始化它。类似这样的事情:
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()
,我将得到一个空指针异常。据我所知,从这里和这里所问的其他一些问题中,我有几个选择,但没有一个看起来很清楚(也许我遗漏了什么):
使用“运行”设置服务
设置应用程序时,请执行以下操作:
myApp.run(function ($http, MyService) {
$http.get('data.json').success(function (data) {
MyService.setData(data);
});
});
那么我的服务将如下所示:
myModule.service('MyService', function() {
var myData = null;
return {
setData: function (data) {
myData = data;
},
doStuff: function () {
return myData.getSomeData();
}
};
});
这在某些时候起作用,但如果异步数据的时间恰好比初始化所有内容所需的时间长,则在调用dostuff()
时会出现空指针异常
使用promise对象
这可能有用。唯一的缺点是,在我调用MyService的任何地方,我都必须知道doStuff()返回一个Promission,并且所有代码都必须提供给我们then
以便与Promission交互。我宁愿等到myData返回后再加载my应用程序。
手动引导
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 Var我可以将JSON直接发送到全局Javascript变量:
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变量,气味很难闻。
这是我唯一的选择吗?这些选项中有一个比其他选项好吗?我知道这是一个相当长的问题,但我想表明我已经尝试探索我的所有选择。如有任何指导,将不胜感激。
基于Martin Atkins的解决方案,这里有一个完整、简洁的纯角度解决方案:
(function() {
var initInjector = angular.injector(['ng']);
var $http = initInjector.get('$http');
$http.get('/config.json').then(
function (response) {
angular.module('config', []).constant('CONFIG', response.data);
angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
}
);
})();
该解决方案使用一个自动执行的匿名函数来获取$HTTP服务,请求配置,并在配置变得可用时将其注入到名为config的常量中。
完成后,我们等待文档准备就绪,然后引导Angular应用程序。
这比Martin的解决方案稍有增强,Martin的解决方案将获取配置推迟到文档准备就绪之后。据我所知,没有理由因此而延迟$HTTP调用。
单元测试
注意:我发现当代码包含在app.js
文件中时进行单元测试时,这个解决方案不能很好地工作。出现这种情况的原因是,当加载JS文件时,上面的代码立即运行。这意味着测试框架(在我的例子中是Jasmine)没有机会提供$HTTP
的模拟实现。
我的解决方案是将这段代码移动到index.html
文件中,这样Grunt/karma/jasmine单元测试基础结构就看不到它了,我对此并不完全满意。
您看过$RouteProvider.When(“/path”,{resolve:{...}
吗?它可以使承诺方法更清晰:
在您的服务中暴露一个承诺:
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();
}
};
});
将解析
添加到路由配置:
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;
}
}})
}):
在解决所有依赖项之前,您的控制器不会被实例化:
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=preview上举了一个例子
问题内容: 我有一个AngularJS服务,我想使用一些异步数据进行初始化。像这样: 显然,这是行不通的,因为如果在返回之前尝试进行调用,我将得到一个空指针异常。据我从阅读这里和这里提出的其他一些问题中所知道的,我有一些选择,但是它们似乎都不是很干净(也许我错过了一些东西): 安装服务“运行” 设置我的应用程序时,请执行以下操作: 然后我的服务将如下所示: 这有时会起作用,但是如果异步数据恰好比初
问题内容: 我在尝试使用异步数据初始化过滤器时遇到麻烦。 过滤器非常简单,它需要将路径转换为名称,但是这样做需要一个对应数组,我需要从服务器中获取该数组。 在返回函数之前,我可以在过滤器定义中执行操作,但是异步方面阻止了该操作 使用诺言可能是可行的,但我对角负载如何过滤没有明确的了解。这篇文章解释了如何通过服务实现这种魔力,但是是否有可能对过滤器做同样的事情? 而且,如果有人对如何翻译这些路径有更
SOFABoot 提供了模块并行启动以及 Spring Bean 异步初始化能力,用于加快应用启动速度。本文介绍如何使用 SOFABoot 异步初始化 Spring Bean 能力以提高应用启动速度。 使用场景 在实际使用 Spring/Spring Boot 开发中,一些 Bean 在初始化过程中执行准备操作,如拉取远程配置、初始化数据源等等。在应用启动期间,这些 Bean 会增加 Spring
我在尝试用异步数据初始化过滤器时遇到了麻烦。 过滤器非常简单,它需要将路径转换为名称,但要做到这一点,它需要一个对应数组,我需要从服务器获取该数组。 在返回函数之前,我可以在过滤器定义中做一些事情,但是异步方面阻止了这一点 使用promise可能是可行的,但我不清楚角度负载是如何过滤的。这篇文章解释了如何通过服务实现这样的魔力,但是对于过滤器也可以这样做吗? 如果有人对如何翻译这些路径有更好的想法
初始化数据 打开MainSetup类,在Daos语句后面插入新建根用户的代码 // 初始化默认根用户 if (dao.count(User.class) == 0) { User user = new User(); user.setName("admin"); user.setPassword
问题内容: 我想以异步方式初始化模块,并提出一些想法。我需要具有Mongo集合列表和其他数据的DB对象,但是为了简洁起见,其中的文件列表确实有用。 我无法导出函数或类,因为我每次都需要返回相同的对象。 首先 想到的最简单的方法是分配给它,然后填充它: 不好的事情–我真的从外面不知道什么时候准备好列表,也没有检查错误的好方法。 *我想出的 *第二种 方法是继承并通知所有人数据库已准备就绪或发生了错误