網站搜尋

typescript - 嘗試將服務注入 Angular 元件時出現錯誤 "EXCEPTION: 無法解析元件的所有參數",為什麼?


我已經在 Angular 中建立了一個基本的應用程式,但我遇到了一個奇怪的問題,我無法將服務注入到我的其中一個元件中。然而,它可以正常注入到我創建的其他三個元件中。

首先,這是服務:

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 的所有參數:(?)。

我在 bootstrap 函數中有這個服務,因此它有一個提供者。而且我似乎能夠毫無問題地將它注入到我其他任何組件的構造函數中。

答案#1

直接從聲明它的檔案中匯入,而不是從匯總檔中匯入。

我不知道究竟是什麼原因導致這個問題,但我看到它被提到過好幾次(可能是某種循環依賴)。

這也應該可以通過改變桶中導出的順序來修復(不清楚細節,但也有提到過)

答案#2

除了之前給出的答案外,似乎當你的可注入服務缺少實際的 @Injectable() 裝飾器時,也會拋出此錯誤。因此,在你調試循環依賴問題以及導入/導出順序之前,先簡單檢查一下你的服務是否實際上有定義 @Injectable()。

這適用於目前最新的 Angular,即 Angular 2.1.0。

我就這個問題提出了一個議題。

答案#3

從 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)) 將會解決這個問題。

參考資料

Angular 2 手冊:ForwardRef

Angular 2 中的前向引用

答案#4

錯誤 #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:你忘了:import { Injectable } from '@angular/core';

//Uncaught ReferenceError: Injectable is not defined
@Injectable
export class MyFooService { ... }

正確:

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

答案#5

如前所述,這個問題是由於桶文件內的匯出順序所造成,而匯出順序的問題是由循環依賴造成的。

更詳細的說明在這裡: https://stackoverflow.com/a/37907696/893630

答案#6

我也透過將服務 A 注入服務 B,反之亦然,遇到過這種情況。

我認為它能快速失敗是件好事,因為這本來就應該盡量避免。如果你希望你的服務更模組化和可重用,最好盡可能避免循環引用。這篇文章突顯了這方面的陷阱。

因此,我有以下建議:

  • 如果你覺得這些類別互動得太頻繁(我指的是特徵羨慕),你可能會想考慮將這兩個服務合併成一個類別。
  • 如果上述方法對你無效,請考慮使用一個 第三方服務,(一個 EventService),兩個服務都可以注入它以交換訊息。

答案#7

為了方便搜尋的人;我遇到了這個錯誤。原因只是缺少了一個 @ 符號。

即。這會產生 無法解析 MyHttpService 的所有參數 錯誤。

Injectable()
export class MyHttpService{
}

添加遺失的 @ 符號即可修復它。

@Injectable()
export class MyHttpService{
}

答案#8

另一種可能性是在 tsconfig.json 中沒有將 emitDecoratorMetadata 設置為 true

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}

答案#9

就我的情況而言,我需要在我的應用程式中添加 import "core-js/es7/reflect"; 才能使 @Injectable 正常工作。

答案#10

除了缺少 @Injectable() 裝飾器之外

在抽象類別中缺少 @Injectable() 裝飾器會導致「無法解析服務的所有參數: (?)」。該裝飾器需要同時存在於 MyService 以及派生類別 BaseService 中。

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

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

答案#11

如果你有服務 A 依賴於服務 B 的 靜態屬性/方法,而服務 B 本身又透過依賴注入依賴於服務 A,你就會收到這個錯誤。因此這是一種循環依賴,儘管它不是,因為該屬性/方法是靜態的。這可能是在與 AOT 結合時出現的錯誤。

答案#12

在我的情況下,這是因為我沒有為建構函數參數宣告類型。

我有類似這樣的東西:

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

然後將它改成下面的程式碼就解決了我的問題。

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