update - dynamic title angular




Winkel-DI-Fehler-AUSNAHME: Es können nicht alle Parameter aufgelöst werden (20)

Ab Angular 2.2.3 gibt es jetzt eine forwardRef() Dienstprogrammfunktion, mit der Sie Provider forwardRef() können, die noch nicht definiert wurden.

Mit "nicht definiert" meine ich, dass die Abhängigkeitsinjektionszuordnung den Bezeichner nicht kennt. Dies geschieht während zirkulärer Abhängigkeiten. In Angular können kreisförmige Abhängigkeiten auftreten, die nur schwer zu entwirren und zu erkennen sind.

export class HeaderComponent {
  mobileNav: boolean = false;

  constructor(@Inject(forwardRef(() => MobileService)) public ms: MobileService) {
    console.log(ms);
  }

}

Durch Hinzufügen von @Inject(forwardRef(() => MobileService)) zum Parameter des Konstruktors im Quellcode der ursprünglichen Frage wird das Problem @Inject(forwardRef(() => MobileService)) .

Verweise

Winkel 2 Handbuch: ForwardRef

Vorverweise in Angular 2

Ich habe eine grundlegende App in Angular erstellt, aber ich habe ein seltsames Problem festgestellt, bei dem ich keinen Dienst in eine meiner Komponenten einbinden kann. Es lässt sich gut in eine der drei anderen Komponenten einspeisen, die ich erstellt habe.

Für den Anfang ist dies der Service:

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;
  }

}

Und die Komponente, mit der es sich weigert zu arbeiten:

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);
  }

}

Der Fehler, den ich in der Browserkonsole erhalte, ist folgender:

AUSNAHME: Es können nicht alle Parameter für HeaderComponent: (?) Aufgelöst werden.

Ich habe den Dienst in der Bootstrap-Funktion, so dass es einen Anbieter hat. Und ich scheine in der Lage zu sein, es ohne Probleme in den Konstruktor einer meiner anderen Komponenten zu injizieren.


Bei mir ist dieser Fehler aufgetreten, als ich diesen Import in der Datei polyfills.ts versehentlich deaktiviert habe. Sie müssen sicherstellen, dass er importiert wird, um diesen Fehler zu vermeiden.

/** 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';

Dies passiert auch, wenn auf eine interface verwiesen wird.

Ändern der interface für die class behoben, mit und ohne @Inject .


Eine andere Möglichkeit besteht darin, dass emitDecoratorMetadata in tsconfig.json nicht auf true gesetzt ist

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}

Für mich war es nur ein Mangel an () in @Injectable. Richtig ist @Injectable ()


Ich bin auch darauf gestoßen, indem ich Service A in Service B injiziert habe und umgekehrt.

Ich finde es gut, dass dies schnell fehlschlägt, da es wahrscheinlich sowieso vermieden werden sollte . Wenn Sie möchten, dass Ihre Dienste modularer und wiederverwendbarer sind, sollten Sie Zirkelverweise so weit wie möglich vermeiden. Dieser post hebt die Gefahren hervor, die damit verbunden sind.

Daher habe ich folgende Empfehlungen:

  • Wenn Sie der Meinung sind, dass die Klassen zu oft interagieren (ich spreche von Feature-Neid ), sollten Sie in Betracht ziehen , die beiden Services in einer Klasse zusammenzuführen .
  • Wenn dies bei Ihnen nicht funktioniert, sollten Sie einen dritten Dienst (einen EventService ) in EventService den beide Dienste zum Austausch von Nachrichten EventService können.

Importieren Sie es aus der Datei, in der es direkt anstelle des Fasses deklariert ist.

Ich weiß nicht genau, was das Problem verursacht, aber ich habe es mehrmals erwähnt (wahrscheinlich eine Art zirkuläre Abhängigkeit).

Es sollte auch reparierbar sein, indem die Reihenfolge der Exporte im Fass geändert wird (keine Details bekannt, wurde aber auch erwähnt)


In meinem Fall habe ich eine Klasse und eine Aufzählung aus derselben Komponentendatei exportiert:

mComponent.component.ts :

export class MyComponentClass{...}
export enum MyEnum{...}

Dann habe ich versucht, MyEnum von einem MyComponentClass MyEnum von MyComponentClass . Dies verursachte den Fehler Kann nicht alle Parameter auflösen .

Durch das Verschieben von MyEnum in einen anderen Ordner als MyComponentClass wurde das Problem behoben!

Wie Günter Zöchbauer erwähnte, geschieht dies, weil eine Dienstleistung oder Komponente zirkulär abhängig ist.


In meinem Fall ist es passiert, weil ich den Typ für einen Konstruktorparameter nicht deklariert habe.

Ich hatte so etwas:

constructor(private URL, private http: Http) { }

und dann in den folgenden Code zu ändern, löste mein Problem.

constructor(private URL : string, private http: Http) {}


In meinem Fall war der Grund der folgende:

  • Mein injizierbarer Dienst A erweiterte eine weitere Klasse B
  • B hatte einen Konstruktor, der ein Argument erforderte
  • Ich hatte in A keinen Konstruktor definiert

Infolgedessen schlug der Standardkonstruktor fehl, wenn versucht wurde, ein Objekt A zu erstellen. Ich habe keine Ahnung, warum dies kein Kompilierungsfehler war.

Ich habe es behoben, indem ich einfach einen Konstruktor in A hinzufügte, der den Konstruktor von B korrekt nannte.


In meinem Fall war es ein Zirkelverweis. Ich hatte MyService Myservice2 aufrufen und MyService2 MyService aufrufen.

Nicht gut :(


Manchmal passiert dies, wenn Sie Angulars eingebautes Modul (HttpClientModule, HttpErrorResponse usw.) in app.module.js deklariert haben. Ich hatte das gleiche Problem, konnte es aber jetzt lösen.

Der Fehler, den ich gemacht habe, war, HttpClientModule in Providers zu erwähnen, anstatt das Winkelmodul zu importieren


Neben dem fehlenden @Injectable()

Das @Injectable() in der abstrakten Klasse hat zur Folge, dass nicht alle Parameter für den Dienst aufgelöst werden können: (?) Der Dekorator muss sowohl in MyService als auch in der abgeleiteten Klasse BaseService

//abstract class
@Injectable()
abstract class BaseService { ... }

//MyService    
@Injectable()
export class MyService extends BaseService {
.....
}

Obwohl die Reihenfolge der exportierten Klassen innerhalb von Fässern erwähnt wurde, kann das folgende Szenario den gleichen Effekt haben.

Angenommen, Sie haben die Klassen A , B und C aus derselben Datei exportiert, wobei A von B und C abhängt:

@Injectable()
export class A {
    /** dependencies injected */
    constructor(private b: B, private c: C) {}
}

@Injectable()
export class B {...}

@Injectable()
export class C {...}

Da die abhängigen Klassen (dh in diesem Fall die Klassen B und C ) Angular noch nicht bekannt sind ( wahrscheinlich zur Laufzeit während des Angular-Abhängigkeitsinjektionsprozesses von Klasse A ), wird der Fehler ausgelöst.

Lösung

Die Lösung besteht darin, die abhängigen Klassen vor der Klasse zu deklarieren und zu exportieren, in der der DI ausgeführt wird.

dh im obigen Fall wird die Klasse A direkt nach der Definition ihrer Abhängigkeiten deklariert:

@Injectable()
export class B {...}

@Injectable()
export class C {...}

@Injectable()
export class A {
    /** dependencies injected */
    constructor(private b: B, private c: C) {}
}

Sie erhalten diesen Fehler, wenn Sie Service A haben , der von einer statischen Eigenschaft / Methode von Service B abhängt, und der Service B selbst von Service A durch Abhängigkeitsinjektion abhängt. Es ist also eine Art zirkuläre Abhängigkeit, obwohl dies nicht der Fall ist, da die Eigenschaft / Methode statisch ist. Wahrscheinlich ein Fehler, der in Kombination mit AOT auftritt.


Wenn Ihr Dienst in derselben Datei wie eine Komponente definiert ist (die ihn verbraucht) und der Dienst nach der Komponente in der Datei definiert ist, wird möglicherweise dieser Fehler angezeigt. Dies ist auf dasselbe 'forwardRef'-Problem zurückzuführen, das andere angesprochen haben. Derzeit ist VSCode nicht besonders gut darin, Ihnen diesen Fehler anzuzeigen, und der Build wird erfolgreich kompiliert.

Das Ausführen des --aot mit --aot kann dieses Problem aufgrund der Funktionsweise des Compilers maskieren (wahrscheinlich im Zusammenhang mit dem Schütteln von Bäumen).

Lösung: Stellen Sie sicher, dass der Dienst in einer anderen Datei oder vor der Komponentendefinition definiert ist. (Ich bin nicht sicher, ob forwardRef in diesem Fall verwendet werden kann, aber es scheint schwerfällig zu sein, dies zu tun).

Wenn ich einen sehr einfachen Dienst habe, der sehr stark an eine Komponente gebunden ist (so etwas wie ein Ansichtsmodell) - z. ImageCarouselComponent , ich kann es ImageCarouselComponent.service.ts damit nicht alles mit meinen anderen Diensten ImageCarouselComponent.service.ts .


Wenn Sie Fassimporte verwenden, sollten Sie als Faustregel den Import von injizierbaren Stoffen in Betracht ziehen.


Zum Nutzen der Suchenden; Ich habe diesen Fehler bekommen. Es war einfach ein fehlendes @ -Symbol.

Dh dies erzeugt den Fehler Can't resolve all parameters for MyHttpService .

Injectable()
export class MyHttpService{
}

Das Hinzufügen des fehlenden @ Symbols behebt das Problem.

@Injectable()
export class MyHttpService{
}

Zusätzlich zu den vorherigen Antworten wird dieser Fehler anscheinend auch ausgegeben, wenn in Ihrem injizierbaren Dienst der eigentliche @Injectable() fehlt. Bevor Sie also das zyklische Abhängigkeitsding und die Reihenfolge Ihrer Importe / Exporte debuggen, überprüfen Sie einfach, ob für Ihren Service tatsächlich @Injectable() definiert ist.

Dies gilt für den aktuellen Angular-Stand, Angular 2.1.0.

Ich habe ein Problem in dieser Angelegenheit aufgeschlagen .





angular2-di