typescript index.ts 中导出的自动排序使应用程序崩溃

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37902476/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:34:52  来源:igfitidea点击:

Automatic ordering of exports in index.ts makes app crash

typescriptangularangular-cli

提问by mollwe

Every time I generate something in my shared folder the index.ts file is rebuilt and exports are put in alphabetical order. This seems to break dependencies for me. Changing order manually so that dependencies is exported before classes with the dependencies makes it work again.

每次我在我的共享文件夹中生成一些东西时,都会重建 index.ts 文件并按字母顺序放置导出。这似乎打破了我的依赖。手动更改顺序,以便在具有依赖项的类使其再次工作之前导出依赖项。

If we have app/shared/auth.guard.ts:

如果我们有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;
    }
}

and app/shared/account.service.ts:

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

}

This doesn't work:

这不起作用:

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.

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.

This works:

这有效:

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

From what I noticed this doesn't apply to all. For example can my user model be exported after auth service and it works fine.

从我注意到的情况来看,这并不适用于所有人。例如,我的用户模型可以在身份验证服务后导出并且工作正常。

I wish I didn't have to change this manually every time. Is there a workaround available? Could I structure the files in a different way?

我希望我不必每次都手动更改它。有可用的解决方法吗?我可以以不同的方式构建文件吗?

Dependencies from package.json:

依赖项来自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"

回答by Michael

This is an issue with ordering of exports in barrels. It has been reported in the angular repo here: https://github.com/angular/angular/issues/9334

这是以桶为单位的出口订购问题。它已在此处的角度存储库中报告:https: //github.com/angular/angular/issues/9334

There are three workarounds:

有三种解决方法:

Change the ordering of exports in your barrels

更改您的桶中的出口顺序

Change the ordering so that module dependencies are listed before their dependants.

更改顺序,以便模块依赖项在其依赖项之前列出。

In this example, AuthGuard dependson AuthService. AuthService is a dependencyof AuthGuard. Therefore, export AuthService before AuthGuard.

在这个例子中,AuthGuard依赖于 AuthService。AuthService 是 AuthGuard 的依赖项。因此,在 AuthGuard 之前导出 AuthService。

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

Don't use barrels at all.

根本不要使用桶。

This is not recommended since it means more imports are required.

不推荐这样做,因为这意味着需要更多的导入。

In this example, you would import AuthService from its file rather than a barrel.

在此示例中,您将从其文件而不是桶中导入 AuthService。

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

Use the systemJS module format rather than commonJS

使用 systemJS 模块格式而不是 commonJS

Change the typescript compiler options to compile to the SystemJS format rather than commonJS. This is done by changing tsconfig.json's compilerOptions.modulefrom commonjsto system.

更改 typescript 编译器选项以编译为 SystemJS 格式而不是 commonJS。这是通过改变tsconfig.json的完成compilerOptions.modulecommonjssystem

Note that when you change that configuration, you'll need to update the moduleIdproperties of all your component decorators from module.idto __moduleNameand declare it in typings.d.tsas follows:

请注意,当您更改该配置时,您需要将moduleId所有组件装饰器的属性从module.idto更新为__moduleNametypings.d.ts如下声明:

declare var __moduleName: string;

This module format is not the default in the Angular-CLItool (official build tool created by the Angular team) and so may not be recommended or supported.

这种模块格式不是Angular-CLI工具(由 Angular 团队创建的官方构建工具)中的默认格式,因此可能不被推荐或支持。



Note: I'm personally not satisfied with any of the workarounds.

注意:我个人对任何解决方法都不满意。

回答by Floydus

I had this issue and this was caused by circular reference. Explanations : within the 'provider service class' I had a reference to a UI page that the constructor referenced this same service causing the circular reference...

我有这个问题,这是由循环引用引起的。说明:在“提供者服务类”中,我引用了一个 UI 页面,该页面的构造函数引用了相同的服务,导致循环引用...

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

So what I had to do, is remove the reference from the service and built a function receiving a callback. No need to reference the UI page from the service and error goes away.

所以我必须做的是从服务中删除引用并构建一个接收回调的函数。无需从服务中引用 UI 页面,错误就会消失。

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

In the app.component class constructor, the one referencing the service, I simply set the link to the callback function like below.

在 app.component 类构造函数中,引用服务的那个,我简单地设置了回调函数的链接,如下所示。

this.servicingClass.setCallBackSpy(this.myCallBackFunctionUsingUIPage);

Hope that helps, my first answer ever :)

希望有帮助,我的第一个答案:)

回答by Kieran Ryan

You can also get this error in Angular2 live and suggests that angular doesn't want to instantiate a service that has already been instantiated. It can happen if you "mis-"include the service e.g. ActivatedRoute from '@angular/router' in the providers property of the @Component class decorator despite having already included the RouterModule in the App.module file, which anyhow registers all router providers and directives for the App.

您也可以在 Angular2 live 中收到此错误,并表明 angular 不想实例化已实例化的服务。如果您“错误地”在@Component 类装饰器的 providers 属性中“错误地”包含了服务,例如来自 '@angular/router' 的 ActivatedRoute,尽管已经在 App.module 文件中包含了 RouterModule,但无论如何它都会注册所有路由器提供程序和应用程序的指令。