web-dev-qa-db-de.com

Die automatische Sortierung der Exporte in index.ts führt zum Absturz der App

Jedes Mal, wenn ich in meinem freigegebenen Ordner etwas generiere, wird die Datei index.ts neu erstellt und die Exporte werden in alphabetischer Reihenfolge aufgeführt. Das scheint Abhängigkeiten für mich zu zerstören. Wenn Sie die Reihenfolge manuell ändern, sodass Abhängigkeiten exportiert werden, bevor Klassen mit den Abhängigkeiten wieder funktionieren.

Wenn wir app/shared/auth.guard.ts haben:

import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';

import { AuthService, User } from './';

@Injectable()
export class AuthGuard implements CanActivate {

    constructor(private accountService: AuthService, private router: Router) { }

    canActivate(next: ActivatedRouteSnapshot): Observable<boolean> {
        let result = this.accountService.currentUser.first().map(user => user != null);

        let route: any[] = ['/login'];

        if (next.url.length) {
            route.Push({ redirectUrl: next.url });
        }

        result.subscribe(isLoggedIn => {
            if (!isLoggedIn) {
                this.router.navigate(route);
            }
        });

        return result;
    }
}

und app/shared/account.service.ts:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

import { User } from './';

const LOCAL_STORAGE_KEY = 'currentUser';

@Injectable()
export class AuthService {
  private currentUserSubject: BehaviorSubject<User>;

  constructor() {
    this.currentUserSubject = new BehaviorSubject<User>(this.getUserFromLocalStorage())
    this.currentUserSubject.subscribe(user => this.setUserToLocalStorage(user));
  }

  logIn(userName: string, password: string) : Observable<User> {
    this.currentUserSubject.next({
      id: userName,
      userName: userName,
      email: userName
    });

    return this.currentUser.first();
  }

  logOut() {
    this.currentUserSubject.next(null);
  }

  get currentUser(): Observable<User> {
    return this.currentUserSubject.asObservable();
  }

  private getUserFromLocalStorage(): User {
    let userString = localStorage.getItem(LOCAL_STORAGE_KEY);

    if (!userString) {
      return null;
    }

    return JSON.parse(userString);
  }

  private setUserToLocalStorage(user: User) {
    if (user) {
      localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(user));
    }
    else {
      localStorage.removeItem(LOCAL_STORAGE_KEY);
    }
  }

}

Das geht nicht:

export * from './auth.guard';
export * from './auth.service';

Unhandled Promise rejection: Error: Cannot resolve all parameters for 'AuthGuard'(undefined, Router). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'AuthGuard' is decorated with Injectable.

Das funktioniert:

export * from './auth.service';
export * from './auth.guard';

Soweit mir aufgefallen ist, gilt dies nicht für alle. Zum Beispiel kann mein Benutzermodell nach dem Auth-Service exportiert werden und es funktioniert einwandfrei.

Ich wünschte, ich müsste das nicht jedes Mal manuell ändern. Gibt es eine Problemumgehung? Könnte ich die Dateien anders strukturieren?

Abhängigkeiten von package.json:

"@angular/common": "^2.0.0-rc.2",
"@angular/compiler": "^2.0.0-rc.2",
"@angular/core": "^2.0.0-rc.2",
"@angular/forms": "^0.1.0",
"@angular/http": "^2.0.0-rc.2",
"@angular/platform-browser": "^2.0.0-rc.2",
"@angular/platform-browser-dynamic": "^2.0.0-rc.2",
"@angular/router": "^3.0.0-alpha.7",
"bootstrap": "^3.3.6",
"es6-shim": "0.35.1",
"moment": "^2.13.0",
"ng2-bootstrap": "^1.0.17",
"reflect-metadata": "0.1.3",
"rxjs": "5.0.0-beta.6",
"slideout": "^0.1.12",
"systemjs": "0.19.26",
"zone.js": "0.6.12"

devDependencies:

"angular-cli": "1.0.0-beta.6"
13
mollwe

Dies ist ein Problem bei der Bestellung von Exporten in Fässern. Es wurde hier im Winkel-Repo berichtet: https://github.com/angular/angular/issues/9334

Es gibt drei Problemumgehungen:

Ändern Sie die Reihenfolge der Exporte in Ihren Fässern

Ändern Sie die Reihenfolge, sodass die Modulabhängigkeiten vor ihren Abhängigen aufgeführt werden.

In diesem Beispiel ist AuthGuard abhängig von AuthService abhängig. AuthService ist ein Abhängigkeit von AuthGuard. Exportieren Sie deshalb AuthService vor AuthGuard.

export * from './auth.service';
export * from './auth.guard';

Verwenden Sie keine Fässer.

Dies wird nicht empfohlen, da mehr Importe erforderlich sind.

In diesem Beispiel würden Sie AuthService aus seiner Datei und nicht aus einem Fass importieren.

import { AuthService } from './auth.service';
import { User } from './';

Verwenden Sie das systemJS-Modulformat anstelle von commonJS

Ändern Sie die TypeScript-Compileroptionen, um das SystemJS-Format anstelle von commonJS zu kompilieren. Dies geschieht durch Ändern von compilerOptions.module von tsconfig.json von commonjs in system.

Wenn Sie diese Konfiguration ändern, müssen Sie die moduleId-Eigenschaften aller Ihrer Komponentendekoratoren von module.id auf __moduleName aktualisieren und in typings.d.ts wie folgt deklarieren:

declare var __moduleName: string;

Dieses Modulformat ist nicht die Standardeinstellung im Angular-CLI Tool (offizielles Build-Tool, das vom Angular -Team erstellt wurde) und wird daher möglicherweise nicht empfohlen oder unterstützt.


Hinweis: Ich bin mit keiner der Problemumgehungen persönlich zufrieden.

32
Michael

Ich hatte dieses Problem und dies wurde durch einen Zirkelverweis verursacht. Erklärungen: Innerhalb der 'Provider-Serviceklasse' hatte ich einen Verweis auf eine UI-Seite, die der Konstruktor auf denselben Service verwies, der den Zirkelverweis verursachte.

import { MyUIPage } from "../pages/example/myuipage";

Was ich also tun musste, ist, die Referenz aus dem Dienst zu entfernen und eine Funktion zu erstellen, die einen Rückruf erhält. Es ist nicht erforderlich, die UI-Seite des Dienstes zu referenzieren, und der Fehler wird behoben.

public setCallBackSpy(callback)
{
   this.callBackSpy = callback;
}

Im app.component-Klassenkonstruktor, demjenigen, der auf den Dienst verweist, setze ich einfach die Verknüpfung zur Callback-Funktion wie folgt.

this.servicingClass.setCallBackSpy(this.myCallBackFunctionUsingUIPage);

Hoffe das hilft, meine erste Antwort überhaupt :)

3
Floydus

Sie können diesen Fehler auch in Angular2 live erhalten und schlägt vor, dass Angle einen bereits instanziierten Dienst nicht instanziieren möchte. Dies kann passieren, wenn Sie den Dienst "falsch" einschließen, z. ActivatedRoute von '@ angle/router' in der provider-Eigenschaft des @Component-Klassendekorators, obwohl das RouterModule bereits in der App.module-Datei enthalten ist, die trotzdem alle Router-Provider und Anweisungen für die App registriert.

1
Kieran Ryan