javascript - AngularJS : Initialize service with asynchronous data

标签 javascript angularjs asynchronous service angular-promise

我有一个 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() 我将得到一个空指针异常。据我所知,通过阅读其他一些问题 herehere我有几个选择,但没有一个看起来很干净(也许我遗漏了一些东西):

使用“运行”设置服务

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

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() 返回一个 promise ,并且所有代码都必须让我们 then 与 promise 进行交互。我宁愿等到 myData 返回后再加载我的应用程序。

手动引导

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 变量:

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

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

最佳答案

你看过$routeProvider.when('/path',{ resolve:{...} ?它可以让 Promise 方法更简洁一些:

在您的服务中公开 promise :

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 添加到您的路由配置中:

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;
      }
    }})
  }):

在解决所有依赖关系之前,您的 Controller 不会被实例化:

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

关于javascript - AngularJS : Initialize service with asynchronous data,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16286605/

相关文章:

Javascript 调试困难,因为浏览器不刷新脚本!

javascript - HTML5 多个画​​布在 Chrome 中运行良好,但在 Firefox 中它仅在第一个 Canvas 中运行

javascript - 优化 ng-repeat 次数 |angularJS

c# - IAsyncEnumerable 或 IAsyncEnumerator 的工厂

javascript - SharePoint 2013计算列(文本+日期)

javascript - 如何在 jQuery 中制作动画时禁用点击?

javascript - 如何使用 AngularJS 确保客户端在文本区域中有足够的单词来禁用/启用按钮?

javascript - Amazon S3 上传图像 - 直接从浏览器使用 Angular js

ios - 异步加载 UIView

spring-boot - Spring Cloud Gateway 可以与非异步的微服务一起使用吗?