web-dev-qa-db-fra.com

La commande automatique des exportations dans index.ts provoque le blocage de l'application

Chaque fois que je génère quelque chose dans mon dossier partagé, le fichier index.ts est reconstruit et les exportations sont classées par ordre alphabétique. Cela semble rompre les dépendances pour moi. La modification manuelle de l'ordre de sorte que les dépendances soient exportées avant que les classes contenant ces dépendances ne le rende opérationnel.

Si nous avons app/shared/auth.guard.ts:

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

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

}

Cela ne marche pas:

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.

Cela marche:

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

D'après ce que j'ai remarqué, cela ne s'applique pas à tous. Par exemple, mon modèle d'utilisateur peut-il être exporté après le service d'authentification et cela fonctionne correctement.

Je souhaite ne pas avoir à changer cela manuellement à chaque fois. Existe-t-il une solution de contournement? Pourrais-je structurer les fichiers d'une manière différente?

Dépendances à partir de 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

Ceci est un problème avec la commande des exportations en barils. Il a été rapporté dans le repo angulaire ici: https://github.com/angular/angular/issues/9334

Il existe trois solutions de contournement:

Changer la commande des exportations dans vos fûts

Modifiez l'ordre afin que les dépendances de module soient répertoriées avant leurs dépendants.

Dans cet exemple, AuthGuard dépend d'AuthService. AuthService est une dependency de AuthGuard. Par conséquent, exportez AuthService avant AuthGuard.

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

Ne pas utiliser de barils du tout.

Ce n'est pas recommandé car cela signifie que plus d'importations sont nécessaires.

Dans cet exemple, vous importeriez AuthService à partir de son fichier plutôt que d'un tonneau.

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

Utilisez le format de module systemJS plutôt que commonJS

Modifiez les options du compilateur TypeScript pour compiler au format SystemJS plutôt que commonJS. Ceci est fait en remplaçant le compilerOptions.module de tsconfig.json de commonjs par system.

Notez que lorsque vous modifiez cette configuration, vous devez mettre à jour les propriétés moduleId de tous vos décorateurs de composants de module.id à __moduleName et les déclarer dans typings.d.ts comme suit:

declare var __moduleName: string;

Ce format de module n'est pas le format par défaut de l'outil Angular-CLI (outil de construction officiel créé par l'équipe Angular) et peut donc ne pas être recommandé ou pris en charge.


Remarque: Personnellement, je ne suis satisfait d'aucune des solutions de contournement.

32
Michael

J'ai eu ce problème et cela a été causé par une référence circulaire. Explications: Au sein de la 'classe de service fournisseur', j'avais une référence à une page d'interface utilisateur à laquelle le constructeur faisait référence à ce même service, d'où la référence circulaire ...

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

Donc, ce que je devais faire, c'est supprimer la référence du service et créer une fonction recevant un rappel. Pas besoin de référencer la page d'interface utilisateur du service et l'erreur disparaît.

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

Dans le constructeur de la classe app.component, celui référençant le service, je règle simplement le lien vers la fonction de rappel comme ci-dessous.

this.servicingClass.setCallBackSpy(this.myCallBackFunctionUsingUIPage);

J'espère que ça aide, ma première réponse jamais :)

3
Floydus

Vous pouvez également obtenir cette erreur dans Angular2 live et suggérer qu'angular ne souhaite pas instancier un service déjà instancié. Cela peut arriver si vous "incluez" le service, par exemple. ActivatedRoute à partir de '@ angular/router' dans la propriété providers du décorateur de classe @Component, bien que le routeur RouterModule ait déjà été inclus dans le fichier App.module, qui enregistre néanmoins tous les fournisseurs de routeurs et les directives de l'application.

1
Kieran Ryan