アプリの構成、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

回答:


158

一番下の行は:

  • プロバイダー構成セクションにサービスを注入することはできません
  • あなたは、CAN、プロバイダのサービスを初期化セクションにサービスを注入します

詳細:

Angularフレームワークには2フェーズの初期化プロセスがあります。

フェーズ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 

このエラーが実際に言っているのは$httpProvider$httpサービスの作成に使用されるがまだ準備されていないということです(まだ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フェーズ中に実行され、このコードが機能します。


63
良い答えですが、構成中にサービスを挿入できないことについては説明していますが、構成中にHTTP POST / GETを行う方法については説明していません。これは、APIによって提供される値を使用して設定されるアプリケーションにとって重要です。
Sean O'Dell 2013年

3
@bebraw&Kosmetika-構成フェーズ中に要求する必要があると私が思う唯一のことは、ある種の設定オブジェクトです。APIエンドポイント、ユーザー情報、ユーザーのロケールと言語設定などが含まれている可能性があります。その場合は、JavaScriptソースに何らかの方法でその情報を含めることをお勧めします。index.htmlでサーバー側レンダリングを使用して、いくつかの設定を入れ、アプリが初期化される前に使用できるようにすることができます。それ以外は、ポストイニシャルの方法を理解しようと思います
ショーンクラークヘス

2
@Sean:HTTP POST / GETを作成する方法はOPとは別の質問であり(構成フェーズ内で$ httpを使用することは可能ですか?)、おそらく完全に別の投稿に値するでしょう。Angularの設定フェーズは同期しているため、サーバー側のデータを設定コードに提供する良い方法は、サーバー側のレンダリング中にHTMLページでJavaScriptオブジェクトとしてレンダリングすること<script>var config = <% = mySettings.toJson() %>;</script>です(例:)。これは、等PHPのためのSmarty、Python用Jinja2の、NodeJS用ヌンチャク、としてテンプレートエンジンを使用して行うことができる
トレバー

4
@threed:サーバー上のHTMLまたはjsに構成データを直接挿入することは、クライアントコードが同じサーバーからのものである場合にのみ機能します。CORSを使用すると、クライアントコードを別のサーバーから提供し、データを別のサーバーから提供することが可能(かつ非常に望ましい)です。このような場合、HTTPを使用して構成データを取得する必要があります。
バーナード

4
これは答えですが、尋ねられた質問に対する答えではありません。
エリック

64

これはあなたに小さなレバレッジを与えるかもしれません:

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

ただし、成功/エラーのコールバックによって、アプリの起動とサーバーの応答の間の競合状態が続く可能性があることに注意してください。


6
私のプロバイダーにとって「受け入れられた答え」は失敗しました...私は2日間の欲求不満を費やして、希望なくしてその仕事を作ろうとしました。あなたのアプローチはすぐに機能しました。
Dave Alperovich、2015年

ここで作成されたインスタンスが「実際の」サービスシングルトンであるか、Angularが実際のインジェクターマジックを実行したときに破棄されるサービスのインスタンスであるかを明確にできますか?
エリック

エリック、現時点では確認できません。ただし、私が通常行うこと(該当する場合)はangular.injector(['mymodule'])-ですが、このアプローチを$httpサービスに使用できるかどうかはわかりません。私が持っていると言いたいです。これが役立つかどうか
コーディ

2
これは受け入れられる答えになるはずです。これを機能させるために苦労しましたが、この方法で問題はすぐに解決しました。これは非常に一般的な問題かもしれません。ありがとう@Cody
iamdash

5
承認されたソリューションがプロバイダーで$ httpを使用しても機能しないことを確認しました。しかし、@ Codyの答えはうまくいきます
Dino

1

これは古い質問です。ライブラリのコア機能に依存したい場合、鶏卵の問題が発生しているようです。

基本的な方法で問題を解決する代わりに、私はバイパスしました。ボディ全体をラップするディレクティブを作成します。例

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

mc-body(1回)、EXレンダリングの前に初期化する必要があります。

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 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.