AngularJS:用异步数据初始化服务

AngularJS:用异步数据初始化服务

我有一个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();
        }
    };});

很明显,这是行不通的,因为如果有东西试图调用doStuff()以前myData获取返回,我将得到一个空指针异常。据我所知,从所问的其他问题中,我可以看出这里这里我有几个选择,但没有一个看起来很干净(也许我遗漏了什么):

带有“Run”的安装服务

在设置我的应用程序时,请执行以下操作:

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()

使用承诺对象

这可能管用。唯一的缺点就是我在任何地方都调用MyService,我必须知道doStuff()返回一个承诺,所有的代码都必须返回给我们。then与承诺互动。我宁愿等到我的数据回来后再加载我的应用程序。

手动引导

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变量,它闻起来很难闻。

这是我唯一的选择吗?这些选择中有一个比其他的好吗?我知道这是一个很长的问题,但我想表明,我已经尝试探索我的所有选择。如有任何指导,将不胜感激。


茅侃侃
浏览 649回答 3
3回答

呼如林

基于Martin Atkins的解,这里有一个完整、简洁的纯角度解:(function()&nbsp;{ &nbsp;&nbsp;var&nbsp;initInjector&nbsp;=&nbsp;angular.injector(['ng']); &nbsp;&nbsp;var&nbsp;$http&nbsp;=&nbsp;initInjector.get('$http'); &nbsp;&nbsp;$http.get('/config.json').then( &nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;(response)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;angular.module('config',&nbsp;[]).constant('CONFIG',&nbsp;response.data); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;angular.element(document).ready(function()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;angular.bootstrap(document,&nbsp;['myApp']); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;);})();该解决方案使用自动执行的匿名函数获取$http服务,请求配置,并在配置可用时将其注入一个名为config的常量中。一旦完全完成,我们将等到文档准备就绪,然后引导这个角度应用程序。这是对Martin解决方案的轻微改进,后者将获取配置推迟到文档准备好之后。据我所知,没有理由推迟要求提供$http的费用。单元测试注意:当代码包含在您的代码中时,当单元测试时,我发现此解决方案不能很好地工作。app.js档案。原因是上述代码在加载JS文件时立即运行。这意味着测试框架(在我的例子中是Jasmine)没有机会提供$http.我的解决方案,我并不完全满意,就是把这段代码移到我们的index.html文件,因此Grunt/Karma/Jasmin单元测试基础结构看不到它。
打开App,查看更多内容
随时随地看视频慕课网APP