Angularで基本的なアプリを作成しましたが、コンポーネントの1つにサービスを挿入できないという奇妙な問題が発生しました。それは私が作成した3つの他のコンポーネントのどれにでもうまく注入します。
まず第一に、これはサービスです:
import { Injectable } from '@angular/core';
@Injectable()
export class MobileService {
screenWidth: number;
screenHeight: number;
constructor() {
this.screenWidth = window.outerWidth;
this.screenHeight = window.outerHeight;
window.addEventListener("resize", this.onWindowResize.bind(this) )
}
onWindowResize(ev: Event) {
var win = (ev.currentTarget as Window);
this.screenWidth = win.outerWidth;
this.screenHeight = win.outerHeight;
}
}
そしてそれが動作することを拒否しているコンポーネント:
import { Component, } from '@angular/core';
import { NgClass } from '@angular/common';
import { ROUTER_DIRECTIVES } from '@angular/router';
import {MobileService} from '../';
@Component({
moduleId: module.id,
selector: 'pm-header',
templateUrl: 'header.component.html',
styleUrls: ['header.component.css'],
directives: [ROUTER_DIRECTIVES, NgClass],
})
export class HeaderComponent {
mobileNav: boolean = false;
constructor(public ms: MobileService) {
console.log(ms);
}
}
ブラウザのコンソールに表示されるエラーはこれです。
例外:HeaderComponentのすべてのパラメータを解決できません:(?)。
それはプロバイダを持っているので、私はブートストラップ機能でサービスを持っています。そして、私は他のコンポーネントのコンストラクタに問題なくそれを挿入できるようです。
バレルの代わりに直接宣言されているファイルからインポートします。
何が正確に問題を引き起こしているのかはわかりませんが、何度か言及されているのを見ました(おそらくある種の循環依存)。
それはまたバレルの輸出の順序を変えることによって修理可能であるべきです(細部を知らないが、同様に述べられました)
与えられた前の答えに加えて、それはあなたの注射可能なサービスが実際の@Injectable()
デコレータを欠いているときにもこのエラーが投げられるようです。そのため、循環依存関係とインポート/エクスポートの順序をデバッグする前に、サービスに実際に@Injectable()
が定義されているかどうかを簡単に確認してください。
これは現在のAngular最新、Angular 2.1.0に適用されます。
Angular 2.2.3
の時点で、まだ定義されていないプロバイダを注入することを可能にするforwardRef()
ユーティリティ関数があります。
定義されていないということは、依存性注入マップが識別子を知らないということです。これが循環依存の間に起こることです。 Angularに依存関係を循環させることができますが、それらを解くのは非常に困難です。
export class HeaderComponent {
mobileNav: boolean = false;
constructor(@Inject(forwardRef(() => MobileService)) public ms: MobileService) {
console.log(ms);
}
}
元の質問のソースコードでコンストラクタのパラメータに@Inject(forwardRef(() => MobileService))
を追加することで問題は解決します。
間違った#1: /忘れたデコレータ:
//Uncaught Error: Can't resolve all parameters for MyFooService: (?).
export class MyFooService { ... }
間違った#2: / "@"記号を省略:
//Uncaught Error: Can't resolve all parameters for MyFooService: (?).
Injectable()
export class MyFooService { ... }
間違った#3: / "()"記号を省略
//Uncaught Error: Can't resolve all parameters for TypeDecorator: (?).
@Injectable
export class MyFooService { ... }
間違った#4: /小文字の "i":
//Uncaught ReferenceError: injectable is not defined
@injectable
export class MyFooService { ... }
間違った#5: /忘れました: '@ angular/core'から{Injectable}をインポートしてください。
//Uncaught ReferenceError: Injectable is not defined
@Injectable
export class MyFooService { ... }
正しい:
@Injectable()
export class MyFooService { ... }
すでに述べたように、この問題は循環依存によって引き起こされるバレル内のエクスポート順序によって引き起こされます。
より詳細な説明はここにあります: https://stackoverflow.com/a/37907696/893630
私はまた、サービスAをサービスBに、またはその逆に注入することによってこれに遭遇しました。
おそらく避けなければならないのでこれが速く失敗するのは良いことだと思います 。サービスをよりモジュール化したり再利用したりしたい場合は、循環参照をできるだけ避けることが最善です。この ポスト はそれを取り巻く落とし穴を強調しています。
したがって、私は以下の推奨事項があります。
EventService
)の使用を検討してください。検索者のために私はこのエラーを受けました。それは単に足りない@記号でした。
すなわちこれによりCan't resolve all parameters for MyHttpService
エラーが発生します。
Injectable()
export class MyHttpService{
}
足りない@
シンボルを追加することでそれを修正します。
@Injectable()
export class MyHttpService{
}
私の場合は、import "core-js/es7/reflect";
を機能させるために@Injectable
をアプリケーションに追加する必要がありました。
Service Bのstaticプロパティ/ methodに依存するservice Aがあり、service B自体がserviceに依存する場合、このエラーが発生します依存性注入によるA。プロパティ/メソッドが静的であるというわけではありませんが、それは一種の循環依存です。おそらくAOTと組み合わせて発生するバグです。
不足している@Injectable()
デコレータに加えて
抽象クラスに@Injectable()
デコレータがないと、serviceのすべてのパラメータを解決できません:(?)デコレータは、派生クラスMyService
だけでなくBaseService
にも存在する必要があります。
//abstract class
@Injectable()
abstract class BaseService { ... }
//MyService
@Injectable()
export class MyService extends BaseService {
.....
}
私の場合は、コンストラクタパラメータの型を宣言していないために起こりました。
私はこのようなものがありました:
constructor(private URL, private http: Http) { }
そしてそれを以下のコードに変更することで私の問題は解決しました。
constructor(private URL : string, private http: Http) {}
注入可能なconstructor()メソッドからパラメータを削除することで、私の場合は解決しました。
私にとっては、@ Injectableの中に()
がないのです。正しいのは@Injectable()です
私の場合それはプラグインAuguryのためでした、それを無効にすることはうまくいきます。代替オプションはAOTです、また動作します。
@ Boboss74へのすべてのクレジット、彼はここに答えを投稿しました: https://github.com/angular/angular/issues/23958
私にとっては、誤って無効にされたpolyfills.tsファイルにこのインポートが含まれている場合は、このエラーが発生します。このエラーを回避するには、インポートされたことを確認する必要があります。
/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import 'core-js/es7/reflect';
私にとって問題はさらに厄介なことでした。サービス内でサービスを使用していて、appModuleに依存関係として追加するのを忘れていました。また起きなさい
@Componentデコレータか、コンポーネントが宣言されているモジュールに、プロバイダ配列を追加する必要があります。内部コンポーネントは以下のようにすることができます:
@Component({
moduleId: module.id,
selector: 'pm-header',
templateUrl: 'header.component.html',
styleUrls: ['header.component.css'],
directives: [ROUTER_DIRECTIVES, NgClass],
providers: [MobileService]
})
私の場合、コンストラクタに誤ったパラメータを渡すとこのエラーが発生します。このエラーに関する基本的な考え方は、あなたが知らないうちに関数に間違った引数を渡したことです。
export class ProductComponent {
productList: Array<Product>;
constructor(productList:Product) {
// productList:Product this arg was causing error of unresolved parameters.
this.productList = [];
}
}
私はその議論を削除することでこれを解決しました。
もう1つの可能性は、tsconfig.jsonでemitDecoratorMetadata
をtrueに設定していないことです。
{
"compilerOptions": {
...
"emitDecoratorMetadata": true,
...
}
}
順序付け バレル内からエクスポートされたクラスの言及はあったかもしれませんが、次のシナリオでも同じ効果が得られます。
A
がB
とC
に依存している同じファイル内からクラスA
、B
、およびC
がエクスポートされているとします。
@Injectable()
export class A {
/** dependencies injected */
constructor(private b: B, private c: C) {}
}
@Injectable()
export class B {...}
@Injectable()
export class C {...}
dependent クラス(つまりこの場合はクラスB
とC
)はまだAngularに認識されていないので( おそらくAngularのクラスA
への依存性注入プロセスの実行時)、エラーが発生します。
解決策は、DIが行われるクラスの前に従属クラスを宣言してエクスポートすることです。
つまり、上記の場合、クラスA
はその依存関係が定義された直後に宣言されます。
@Injectable()
export class B {...}
@Injectable()
export class C {...}
@Injectable()
export class A {
/** dependencies injected */
constructor(private b: B, private c: C) {}
}
サービスの名前、つまりコンストラクタ(private myService:MyService )を誤って入力すると、このエラーが発生しました。
スペルミスのサービスについては、Chrome-> Consoleでページを調べることで、どのサービスが問題だったのか(私はいくつかコンストラクタにリストされていた)判断することができました。オブジェクトObject、オブジェクトObject、?を表示すると、メッセージの一部として「パラメータ」配列リストが表示されます。 (またはそのようなもの)。 「?」のところに注意してくださいそれが問題の原因となっているサービスの位置です。
サービスがコンポーネントと同じファイル(それを消費する)で定義され、サービスがafterファイルのコンポーネントで定義されている場合、これを取得できますエラー。これは、他の人が言及した同じ「forwardRef」の問題によるものです。現時点では、VSCodeはこのエラーを表示するのには向いておらず、ビルドは正常にコンパイルされます。
--aot
を指定してビルドを実行すると、コンパイラの動作(おそらくツリーの揺れに関連する)が原因で、この問題を隠すことができます。
解決策:サービスが別のファイルで定義されているか、コンポーネント定義の前に定義されていることを確認してください。 (この場合、forwardRefを使用できるかどうかはわかりませんが、そうするのは面倒です)。
コンポーネント(ビューモデルのようなもの)に強く結び付けられた非常に単純なサービスがある場合-たとえばImageCarouselComponent
、名前をImageCarouselComponent.service.ts
にすると、すべてが他のサービスと混同されないようにできます。
私の場合、その理由は次のとおりです。
結果として、オブジェクトAを作成しようとすると、デフォルトのコンストラクタは失敗しました。なぜこれがコンパイルエラーではなかったのかわかりません。
Aにコンストラクタを追加するだけで修正できました。これはBのコンストラクタと呼ばれていました。
私の場合は "format(date: Date, displayFormat: Object)
"メソッドをオーバーライドするために "NativeDateAdapter
"を拡張しようとしていました。
AngularMaterial-2ではDatePickerです。
だから基本的に私は@Injectable
アノテーションを追加するのを忘れました。
これを私の "CustomDateAdapter"クラスに追加した後:
@Injectable({
providedIn: 'root'
})
エラーが発生しました。
バレルインポートを使用する場合 - 経験則として、まず注射剤をインポートすることを検討してください。
この答え この問題に非常に役立つかもしれません。さらに、私の場合は、サービスをdefault
としてエクスポートすることが原因でした。
間違っています:
@Inject()
export default class MobileService { ... }
正しい:
@Inject()
export class MobileService { ... }
App.module.jsでAngularの作り付けモジュール(HttpClientModule、HttpErrorResponseなど)を宣言したときに時々これが起こります。私も同じ問題に直面しましたが、今は解決しました。
私がした間違いは、Angular ModuleのImportではなくProvidersへのHttpClientModuleの言及でした。
ガッチャ!
上記の答えのどれもがあなたを助けなかったなら、多分あなたはコンポーネントがサービスを注入している同じ file からある要素をインポートしています。
私はもっとよく説明します:
これはサービス file :です。
// your-service-file.ts
import { helloWorld } from 'your-component-file.ts'
@Injectable()
export class CustomService() {
helloWorld()
}
これがコンポーネント file です。
@Component({..})
export class CustomComponent {
constructor(service: CustomService) { }
}
export function helloWorld() {
console.log('hello world');
}
そのため、シンボルが同じコンポーネント内ではなく、同じファイル内にあっても問題が発生します。シンボル(関数、定数、クラスなど)を別の場所に移動すると、エラーは消えます。
私にとっては、@Component
デコレータとComponentクラスの間に空の行があるためです。これにより、デコレータはクラスに適用されませんでした。
エラーのフィードバックが不足しているため、これはデバッグが非常に難しい問題になる可能性があります。実際の循環依存関係を心配している場合は、スタックトレースで調べることが最も重要です。a)サービスの名前b)疑問符のあるそのサービスのコンストラクタパラメータ。このように見えるなら:
authServiceのすべてのパラメータを解決することはできません。([object Object]、[object Object]、[object Object]、[object Object]、?)
それから5番目のパラメータはAuthServiceにも依存するサービスであることを意味します。つまり疑問符は、DIによって解決されなかったことを意味します。
そこから、コードを再構築して2つのサービスを分離するだけです。
私の場合は、同じコンポーネントファイルからClassとEnumをエクスポートしていました。
mComponent.component.ts
:
export class MyComponentClass{...}
export enum MyEnum{...}
それから、私はMyEnum
の子からMyComponentClass
を使用しようとしていました。 すべてのパラメータを解決できないというエラーが発生していました 。
MyEnum
をMyComponentClass
とは別のフォルダーに移動することで、問題は解決しました。
GünterZöchbauerが述べたように、これはサービスまたはコンポーネントが循環的に依存しているために起こっています。
interface
も参照するときに起こります。
interface
をclass
に変更すると、@Inject
の有無にかかわらず動作して修正されました。
私の場合は循環参照でした。 MyServiceからMyservice2 を呼び出し、MyService2からMyServiceを呼び出しました。
良くない :(
私にとってこれは、コンパイル時間を早くするために-aotフラグの使用を止めたためです。
ng serve -aot
私の場合は、依存関係のないサービスに依存関係を持っていたので、サービスクラスにconstructor()
関数を追加しませんでした。私はパラメータなしのコンストラクタを依存サービスクラスに追加しました、そしてすべてが働き始めました。