【问题标题】:use $http inside custom provider in app config, angular.js在应用程序配置中的自定义提供程序中使用 $http,angular.js
【发布时间】:2013-07-04 00:52:18
【问题描述】:

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

主 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 

有什么想法吗?

谢谢!

【问题讨论】:

标签: javascript angularjs angular-services


【解决方案1】:

底线是:

  • 不能将服务注入提供程序配置部分
  • 可以将服务注入到初始化提供者服务的部分

详情:

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

阶段 1:配置

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

第 2 阶段:运行

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 

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

2。将$http服务注入服务初始化函数WILL工作:

//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 阶段执行,因此该代码将起作用。

【讨论】:

  • 很好的答案,但是虽然它解释了如何在配置期间无法注入服务,但它没有解释如何在配置期间进行 HTTP POST/GET。这对于使用 API 提供的值配置的应用程序很重要。
  • @bebraw & Kosmetika - 我认为您在配置阶段唯一需要请求的是某种设置对象。也许它包含 API 端点、用户信息、用户的语言环境和语言设置等。如果是这种情况,我建议以某种方式将该信息包含在 javascript 源中。您可以在 index.html 上使用服务器端呈现来放入一些设置,以便它们在您的应用程序初始化之前可用。其他一切,我会尝试在初始化后弄清楚如何做到这一点
  • @Sean: How to make an HTTP POST/GET is a different question than the OP's (Is it possible to use $http inside the configuration phase?),并且可能完全值得单独发布一个帖子;由于 Angular 配置阶段的同步特性,向配置代码提供服务器端数据的一个好方法是在服务器端呈现期间将其呈现为 HTML 页面中的 javascript 对象(例如<script>var config = <% = mySettings.toJson() %>;</script>)。这可以使用模板引擎来完成,例如 PHP 的 Smarty、Python 的 Jinja2、NodeJS 的 Nunchucks 等。
  • @threed:仅当您的客户端代码来自同一服务器时,将配置数据直接插入服务器上的 HTML 或 js 才有效。使用 CORS,现在可以(并且非常希望)从不同的服务器提供客户端代码,并从单独的服务器提供数据。在这些情况下,我们确实需要使用 HTTP 检索配置数据。
  • 虽然这是一个答案,但它不是所提问题的答案。
【解决方案2】:

这可能会给你一点筹码:

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

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

【讨论】:

  • 我的提供者的“接受的答案”失败了......我花了 2 天的挫折试图让这项工作毫无希望。你的方法立竿见影。
  • 您能否澄清一下这里创建的实例是“真正的”服务单例,还是只是在 Angular 执行其真正的注入器魔法时被丢弃的服务实例。
  • 埃里克,我目前无法确认。但是,我通常做的(如果适用)是angular.injector(['mymodule'])——但我不确定您是否可以将这种方法用于$http 服务。我想说我有。不确定这是否有帮助:-/
  • 这应该是公认的答案。在试图让它发挥作用时,我挣扎了好久,这种方法立即解决了我的问题。我认为这可能是一个非常普遍的问题。谢谢@Cody
  • 我确认接受的解决方案不适用于在提供程序中使用 $http。但是@Cody 的回答确实成功了
【解决方案3】:

这是一个老问题,如果我们想依赖库的核心能力,似乎我们有一些鸡蛋的事情正在发生。

我没有从根本上解决问题,而是绕过。创建一个包裹整个主体的指令。前任。

<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 注入的。 &lt;ui-route /&gt;。但我可能是错的。需要更多调查。

【讨论】:

  • 您能否详细说明您的解决方案?
【解决方案4】:

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

我建议只在配置中使用 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 在成功回调中包含 $,就好像它是一个内部提供者一样。
  • 你说得对,我混合了 $ 和 not-$。我将其更新为 $。
猜你喜欢
  • 2014-08-22
  • 2019-01-29
  • 1970-01-01
  • 2022-08-02
  • 1970-01-01
  • 1970-01-01
  • 2013-05-18
  • 1970-01-01
相关资源
最近更新 更多