在应用配置Angular.js中的自定义提供程序中使用$ http


90

主要问题-可能吗?我没有运气尝试..

主app.js

...
var app = angular.module('myApp', ['services']);
app.config(['customProvider', function (customProvider) {

}]);
...

提供者本身

var services = angular.module('services', []);
services.provider('custom', function ($http) {
});

而且我有这样的错误:

Uncaught Error: Unknown provider: $http from services 

有任何想法吗?

谢谢!



男人,是的,是的,但是我在说的app.config
Kosmetika


我也知道此限制,但认为在提供者内部某种程度上是可能的。–
Kosmetika

Answers:


158

底线是:

  • 不能将服务注入提供者配置部分
  • CAN注入服务成初始化提供者的服务的部分

细节:

Angular框架有两个阶段的初始化过程:

阶段1:配置

在此config阶段,将初始化所有提供程序,并config执行所有部分。这些config部分可能包含配置提供程序对象的代码,因此可以将它们与提供程序对象一起注入。但是,由于提供者是服务对象的工厂,并且在此阶段,提供者尚未完全初始化/配置->您不能在此阶段要求提供者为您创建服务->在配置阶段您不能使用/注入服务。此阶段完成后,所有提供程序都准备就绪(配置阶段完成后,无法再进行任何提供程序配置)。

第二阶段:跑步

run阶段中,run将执行所有部分。在此阶段,提供者已准备就绪,可以创建服务->在此run阶段,您可以使用/注入服务

例子:

1.将$http服务注入提供者初始化功能无法正常工作

//ERRONEOUS
angular.module('myModule').provider('myProvider', function($http) {
    // SECTION 1: code to initialize/configure the PROVIDER goes here (executed during `config` phase)
    ...

    this.$get = function() {
        // code to initialize/configure the SERVICE goes here (executed during `run` stage)

        return myService;
    };
});

由于我们试图将$http服务注入到在该config阶段执行的函数中,因此会出现错误:

Uncaught Error: Unknown provider: $http from services 

该错误实际上是在说$httpProvider用于创建$http服务的尚未准备就绪(因为我们仍处于config阶段中)。

2.将$http服务注入服务初始化功能起作用:

//OK
angular.module('myModule').provider('myProvider', function() {
    // SECTION 1: code to initialize/configure the PROVIDER goes here (executed during `config` phase)
    ...

    this.$get = function($http) {
        // code to initialize/configure the SERVICE goes here (executed during `run` stage)

        return myService;
    };
});

由于我们现在将服务注入到服务初始化函数中,该函数在run阶段中执行,因此该代码将起作用。


63
很好的答案,但是尽管它说明了在配置期间如何无法注入服务,但没有说明如何在配置期间进行HTTP POST / GET。这对于使用API​​提供的值配置的应用程序很重要。
肖恩·奥德尔2013年

3
@bebraw&Kosmetika-我可以认为您在配置阶段需要请求的唯一一件事就是某种设置对象。也许它包含API端点,用户信息,用户的语言环境和语言设置等。如果是这种情况,我建议以某种方式在javascript源中包含该信息。您可以在index.html上使用服务器端渲染来放置一些设置,以便在应用初始化之前可以使用它们。其他所有事情,我都想弄清楚如何在初始化后进行
Sean Clark Hess 2014年

2
@Sean:如何进行HTTP POST / GET与OP的问题不同(是否可以在配置阶段使用$ http?),并且可能一并值得一提;由于Angular的配置阶段具有同步性,将服务器端数据提供给配置代码的一种好方法是在服务器端渲染(例如<script>var config = <% = mySettings.toJson() %>;</script>)期间将其作为javascript对象渲染到HTML页面中。这可以使用模板引擎来完成,例如PHP的Smarty,Python的Jinja2,NodeJS的Nunchucks等。–
Trevor

4
@threed:仅当您的客户端代码来自同一服务器时,才能将配置数据直接插入服务器上的HTML或js中。使用CORS,现在(非常需要)可以从其他服务器提供客户端代码,并从单独的服务器提供数据。在这些情况下,我们确实需要使用HTTP检索配置数据。
伯纳德2014年

4
虽然这是一个答案,但不是所提出问题的答案。
埃里克

64

这可能会给您带来一些杠杆作用:

var initInjector = angular.injector(['ng']);
var $http = initInjector.get('$http');

但是请注意,成功/错误回调可能会使您处于应用启动和服务器响应之间的竞争状态。


6
对于我的提供者来说,“可接受的答案”失败了……我花了2天的挫折试图使这项工作毫无希望。您的方法立即起作用。
Dave Alperovich 2015年

您能否澄清在此创建的实例是“真实”服务单例还是只是Angular进行其真实的注入器魔术操作时丢弃的服务实例。
埃里克

埃里克,我目前无法确认。但是,我通常会做的(如果适用)是angular.injector(['mymodule'])-但是我不确定您是否可以对$http服务使用这种方法。我想说我有。不知道这是否有帮助:-/
Cody 2015年

2
这应该是公认的答案。为了使它正常工作,我奋力挣扎,这种方法立即解决了我的问题。我认为这可能是一个非常普遍的问题。感谢@Cody
iamdash

5
我确认接受的解决方案对于在提供程序中使用$ http无效。但@Cody的回答确实让伎俩
迪诺

1

这是一个古老的问题,如果我们要依赖库的核心功能,似乎我们正在做一些鸡蛋工作。

我所做的只是绕过,而不是从根本上解决问题。创建一个包装整个身体的指令。例如

<body ng-app="app">
  <div mc-body>
    Hello World
  </div>
</body>

现在mc-body需要在渲染之前(一次)进行初始化,例如。

link: function(scope, element, attrs) {
  Auth.login().then() ...
}

Auth 是服务或提供者,例如

.provider('Auth', function() {
  ... keep your auth configurations
  return {
    $get: function($http) {
      return {
        login: function() {
          ... do something about the http
        }
      }
    }
  }
})

在我看来,我确实可以控制引导程序的顺序,这是在常规引导程序解析完所有提供程序配置然后尝试初始化mc-body指令之后。

在我看来,该指令可以领先于路由,因为路由也是通过指令ex注入的。<ui-route />。但是我对此可能是错的。需要更多调查。


您能否详细说明您的解决方案?
马克

-2

在回答您的问题“是否有想法?”时,我会回答“是”。但是,等等,还有更多!

我建议只在配置中使用JQuery。例如:

var app = angular.module('myApp', ['services']);
app.config(['$anyProvider', function ($anyProvider) {
    $.ajax({
        url: 'www.something.com/api/lolol',
        success: function (result) {
            $anyProvider.doSomething(result);
        }
    });
}]);

成功回调中的$ customProvider包括$,就好像它是内部提供程序一样。
杰夫·菲舍尔

1
您是对的,我混合使用$和非$。我将其全部更新为$。
Suamere
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.