封装Web Service数据的Angular服务

时间:2013-12-27 14:49:32

标签: javascript angularjs restangular

我目前正在使用角度js编写一个前端应用程序。

我正在使用Restangular来处理所有REST请求。目前正在加载数据非常完美。

我想做以下事情:

我想编写一个服务/工厂/提供程序,它返回每种语言的名称。此调用只需要在整个工作流程中执行一次(当用户使用应用程序时,语言不太可能)。

所以我尝试过这样的事情:

'use strict';

angular.module('maroziFrontendApp')
  .service('LanguagesService', function(Restangular) {
    this.languages = Restangular.one('languages').get();
  });

但是当我在我的控制器(或Restangular元素变换器)中注入它时,我只能得到承诺。然后,我必须做另一个回调,这会弄乱工作流程。

我也尝试过:

'use strict';

angular.module('maroziFrontendApp')
  .service('LanguagesService', function(Restangular) {
    Restangular.one('languages').get().then(function(languages) {
      this.languages = languages;
    });
  });

但是这会在注入时返回undefined

澄清:

我希望在命中控制器(或elementtransformer)之前加载语言。我无法使用resolve,因为我不仅在控制器中使用此服务。

有简单的方法吗?

5 个答案:

答案 0 :(得分:3)

从版本1.2.0开始,您现在也可以在Restangular中使用$object

所以你的代码是:

angular.module('maroziFrontendApp')
  .service('LanguagesService', function(Restangular) {
    this.languages = Restangular.one('languages').get().$object;
  });

然后在你的控制器中:

$scope.languages = LanguageService.languages

在HTML中:

<span>{{languages.name}}</span>

这看起来好多了:)

答案 1 :(得分:1)

在您的第二次尝试中,您在回调函数中引用了this,这就是为什么我认为您正在获取undefined。以下示例解决了该问题。

'use strict';

angular.module('maroziFrontendApp')
  .service('LanguagesService', function(Restangular) {
    var self = this;
    Restangular.one('languages').get().then(function(languages) {
      self.languages = languages;
    });
  });

这种方法仍然存在问题,因为需要使用LanguagesService的代码需要某种方式来了解它何时可用。

您可能需要考虑向用户显示某种“正在加载”的消息,然后使用module.run()方法中的链式承诺加载所有必需的数据。加载所有数据后,您可以将用户重定向到应用程序入口点。

另一个需要考虑的选择是,如果应用程序的所有用户的语言列表都相同,请尝试生成并包含类似以下示例的javascript文件,您不必担心异步问题。

angular.module("maroziFrontendApp")
  .value("Languages", function() {
    return {
      "en": "English",
      "fr": "French",
      "es": "Spanish"
    };
  });

答案 2 :(得分:1)

由于AJAX调用是异步的,因此无法确保在执行控制器函数之前加载语言。

对于它的价值,Restangular promises有一个名为$object的属性。一旦返回响应,它就会被结果填充。

this.languages = Restangular.one('languages').get().$object;

答案 3 :(得分:0)

在/ loading之类的其他路线上加载数据,加载数据后,您可以重定向到您希望能够立即从服务中访问数据的页面。

答案 4 :(得分:0)

我可以想到一个非正统的解决方案,你手动引导角度应用程序。

首先启动服务,然后再启动。您必须删除当然的ng-app指令

var module = angular.module("app",['restangular','ngMockE2E']);

module.factory('LanguagesService', function(Restangular, $q) {
    var service = {};
    service.init = function() {
        var defered = $q.defer();
        Restangular.one('languages').get().then(function(languages) {
            service.languages = languages;
            service.init = undefined;
            defered.resolve();
        });
        return defered.promise;
    }
    return service;
});

//Manual bootstrap
function bootstrap() {
    var $injector = angular.injector(['app']);
    $injector.invoke(function ($rootScope, $compile, $document, LanguagesService) {
        LanguagesService.init().then(function() {
            $compile($document)($rootScope);       
        });

    });
}
bootstrap();

请参阅http://jsfiddle.net/VtazD/1/

缺点当然是初始加载时间,并且在应用程序完全加载之前会显示胡须,但我确定有解决方案。