ข้อยกเว้น: ไม่สามารถแก้ไขพารามิเตอร์ทั้งหมด


431

ฉันได้สร้างแอพพื้นฐานใน Angular 2 แต่ฉันพบปัญหาแปลก ๆ ที่ฉันไม่สามารถฉีดบริการเข้าไปในหนึ่งในองค์ประกอบของฉัน อย่างไรก็ตามมันสามารถแทรกเข้าไปในองค์ประกอบอื่น ๆ สามอย่างที่ฉันสร้างขึ้นได้

สำหรับผู้เริ่มต้นนี่คือบริการ:

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 ดังนั้นจึงมีผู้ให้บริการ และดูเหมือนว่าฉันจะสามารถฉีดลงในคอนสตรัคเตอร์ของส่วนประกอบอื่น ๆ ของฉันได้โดยไม่มีปัญหา


14
อาจจะนำเข้าหรือไม่ คือ(Barrel)? คุณสามารถลองนำเข้าจากไฟล์ที่มีการประกาศโดยตรงแทนได้หรือไม่? '../'index.ts
GünterZöchbauer

น่าอัศจรรย์ที่ดูเหมือนว่าจะได้รับการแก้ไข! แปลกที่มันจะไม่ทำงานโดยใช้กระบอกเมื่อส่วนประกอบอื่น ๆ ที่ฉันทดสอบการบริการด้วยได้ หากคุณต้องการโพสต์ว่าเป็นคำตอบแทนความคิดเห็นฉันจะยอมรับมัน
Keith Otto

11
โดยทั่วไปการอ้างอิงแบบวงกลม
Gary

ฉันเคยมีปัญหานี้กับการพึ่งพาแบบวงกลมเช่นกัน มันน่าสังเกตว่าเว็บแพ็คเวอร์ชันใหม่นั้นดีกว่ามากในการบอกคุณ
Enn

ดูเหมือนว่าการพึ่งพาแบบวงกลมถ้าคุณใช้เชิงมุม> = 4 เพื่อให้คุณสามารถกำจัด intex.ts (บาร์เรล) และนำเข้าสิ่งที่คุณต้องการโดยตรง
Rammgarot

คำตอบ:


457

นำเข้าจากไฟล์ที่มีการประกาศโดยตรงแทนที่จะเป็นบาร์เรล

ฉันไม่รู้ว่าอะไรเป็นสาเหตุของปัญหา แต่ฉันเห็นมันพูดถึงหลายครั้ง (อาจเป็นการพึ่งพาแบบวงกลม)

ควรแก้ไขได้โดยเปลี่ยนลำดับการส่งออกในถัง (ไม่ทราบรายละเอียด แต่ถูกกล่าวถึงเช่นกัน)


16
สิ่งนี้ถูกต้องถ้าคุณมีตัวอย่างของบริการที่ถูกฉีดเข้าไปในบริการอื่น ๆ ที่หนึ่งต้องมาก่อนในถัง
Joao Garin

17
ทีม Angular2 ไม่แนะนำบาร์เรลอีกต่อไปเพราะปัญหาดังกล่าวมากมาย ดีใจที่ได้ยินฉันช่วยได้ :)
GünterZöchbauer

13
ไม่ทราบว่าทีม Angular 2 ไม่แนะนำบาร์เรล ถ้าเป็นเช่นนั้นพวกเขาควรทราบว่าในอภิธานศัพท์ที่กล่าวถึงประโยชน์ของพวกเขา และโครงการอย่างangular2-webpack-starterไม่ควรใช้มัน
บลู

3
มันตะเข็บนี้ได้รับการแก้ไข (ไม่ใช่ปัญหา2.0.2) ฉันพบว่าถังยังคงมีประโยชน์โดยเฉพาะเมื่อฉันต้องการนำเข้ารุ่นและบริการระหว่างโมดูลที่แตกต่างกัน นี่import { cleanValues, getState, FirebaseService, NotificationService, ... } from '../../shared/services';คือความเจ็บปวดเมื่อมันไม่ทำงาน (; NgModuleไม่ได้ช่วยบริการเดี่ยว ...
Sasxa

3
ฉันขอแก้ไขโดยการเปลี่ยนลำดับของการส่งออกในไฟล์บาร์เรล (index.ts) ขอบคุณมาก
สป็อค

331

นอกเหนือจากคำตอบก่อนหน้าที่ระบุดูเหมือนว่าข้อผิดพลาดนี้จะถูกโยนเช่นกันเมื่อบริการการฉีดของคุณหายไปจาก@Injectable()มัณฑนากรจริง ดังนั้นก่อนที่คุณจะดีบักสิ่งที่ขึ้นต่อกันของวัฏจักรและลำดับการนำเข้า / ส่งออกของคุณให้ตรวจสอบง่ายๆว่าบริการของคุณได้@Injectable()กำหนดไว้จริงหรือไม่

สิ่งนี้ใช้กับ Angular ล่าสุด Angular 2.1.0

ฉันเปิดปัญหาในเรื่องนี้


ใช่ข้อผิดพลาดนี้เป็นเพราะคุณลืมที่จะเพิ่ม @Injectable และเช่นคุณอาจจะนำเข้าRouterจาก '@ angular / เราเตอร์' และหากไม่มีการฉีดนั้นข้อผิดพลาดนี้จะเกิดขึ้นเสมอ (ทันทีที่คุณตัดสินใจที่จะทำหนึ่งบรรทัด การใช้รหัสที่ฉีดเราเตอร์
Eric Bishard

คำตอบที่ยอดเยี่ยมปัญหาของฉันคือฉันได้เพิ่มวิธีการในบริการของฉันและไม่ได้เพิ่มเครื่องหมายทวิภาคกึ่งหลังวงเล็บปีกกาสุดท้าย ฉันไม่รู้ว่าทำไมมันต้องเป็นแบบนี้ แต่มันก็ไม่ได้เป็นเช่นนั้นในคลาสคอมโพเนนต์ ... ตอนนี้ฉันดีใจมากที่ได้ดำเนินการต่อไป!
egimaben

ฉันมีรูปแบบง่าย ๆ ที่ทำให้ฉันมีข้อผิดพลาดนี้ ฉันใช้ทางลัดที่คุณสร้างคุณสมบัติของคุณในตัวสร้างของโมเดล ประเภทของคุณสมบัติเป็นสตริงเท่านั้นและ int ทันใดนั้นปัญหานี้ก็เริ่มเกิดขึ้น การเพิ่ม @Injectable () แก้ไขปัญหา แปลกเพราะไม่มีรุ่นอื่นของฉันเพิ่มเข้ามา ฉันต้องเพิ่มว่าฉันอัพเกรดห้องสมุดไม่กี่แห่งก่อนที่จะเพิ่มโมเดลใหม่นี้ อาจมีบางอย่างเกี่ยวข้องกับมัน แต่ทำงานตอนนี้ ขอบคุณ
Moutono

@ โมโตโร่ถูกต้อง ด้วยนวกรรมิกที่ว่างเปล่าในบริการของคุณการฉีดที่พึ่งพาดูเหมือนจะไม่ถูกทริกเกอร์และ@injectable()ไม่จำเป็น ซึ่งเป็นสิ่งที่แปลกอีกอย่างหนึ่งในตัวเอง สำหรับการวัดที่ดีฉันยังคงเพิ่มมันเพียงแค่เมื่อคุณควรตัดสินใจที่จะฉีดอะไรสักอย่าง
JP ten Berge

โปรดทราบว่าหากบริการของคุณมีคลาสพื้นฐานที่จำเป็นต้องตกแต่งด้วย @Injectable ()
Sam Shiles

110

ในฐานะของเชิงมุม2.2.3ขณะนี้มีforwardRef()ฟังก์ชั่นยูทิลิตี้ที่ช่วยให้คุณสามารถฉีดผู้ให้บริการที่ยังไม่ได้กำหนด

โดยไม่ได้กำหนดฉันหมายความว่าแผนที่การฉีดพึ่งพาไม่รู้จักตัวระบุ นี่คือสิ่งที่เกิดขึ้นในระหว่างการพึ่งพาแบบวงกลม คุณสามารถมีการพึ่งพาแบบวนรอบในเชิงมุมซึ่งยากต่อการแยกและดู

export class HeaderComponent {
  mobileNav: boolean = false;

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

}

การเพิ่ม@Inject(forwardRef(() => MobileService))พารามิเตอร์ของ Constructor ในซอร์สโค้ดของคำถามจะช่วยแก้ปัญหาได้

อ้างอิง

คู่มือเชิงมุม 2: ForwardRef

การส่งต่ออ้างอิงในเชิงมุม 2


3
forwardRef()มีอยู่แล้วในอัลฟา ;-) มันจำเป็นเฉพาะในกรณีที่Mobileมีการประกาศบริการเพิ่มเติมลงในไฟล์เดียวกัน ถ้าคลาสอยู่ในไฟล์ที่ต่างกันก็ไม่จำเป็นต้องใช้forwardRef()
GünterZöchbauer

4
GünterZöchbauerฉันยังคงพยายามหาปัญหาจริงเกี่ยวกับรหัสของฉัน แต่ในขณะเดียวกันforwardRef()ก็ช่วยกำจัดCan't resolve all parameters for ...ข้อความ อย่างน้อยส่วนประกอบก็ใช้งานได้ในขณะที่ฉันกำลังมองหาวิธีแก้ปัญหาที่ดีกว่า (และใช่พึ่งพาความล้มเหลวที่จะถูกนำเข้าโดยตรงจากแฟ้ม)
Nik

4
@ GünterZöchbauerฉันได้อัปเดตคำตอบสำหรับการอ้างอิงแล้ว ฉันไม่ได้พยายามที่จะละทิ้งคำตอบของคุณ แต่นี่แก้ปัญหาได้จริงและผู้คนจำเป็นต้องรู้ หากคุณ google forwardRefคำถามที่มีผลไม่ที่บอกว่าจะใช้ หายากมาก พาฉันทั้งวันเมื่อวานนี้เพื่อแก้ไขปัญหานี้
Reactgular

แปลก. ฉันโพสต์คำตอบอย่างน้อยหนึ่งโหลที่แนะนำให้ใช้foreardRefตัวเอง แต่ไม่NgModuleแนะนำอีกต่อไปหลังจากนั้น ฉันไม่กังวลเกี่ยวกับการสูญเสียพนักงาน ฉันแค่อยากรู้ว่าทำไมคุณถึงพบสิ่งนี้หลังจากสิ่งนี้ไม่ปรากฏขึ้นอีกต่อไปตั้งแต่ไม่กี่เดือน ฉันจะดูใกล้ ๆ เมื่อฉันกลับบ้านในอีกไม่กี่วัน ขอบคุณมากสำหรับความคิดเห็น
GünterZöchbauer

2
หากใครบางคนหลงทางเกี่ยวกับการนำเข้า: import {Component, Inject, ForwardRefFn, forwardRef} จาก '@ angular / core';
Natanael

69

ผิด # 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:คุณลืม: นำเข้า {Injectable} จาก '@ angular / core';

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

แก้ไข:

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

27

ตามที่ระบุไว้แล้วปัญหาเกิดจากการส่งออกสั่งภายในบาร์เรลซึ่งเกิดจากการอ้างอิงแบบวงกลม

คำอธิบายโดยละเอียดเพิ่มเติมอยู่ที่นี่: https://stackoverflow.com/a/37907696/893630


3
การสั่งซื้อไม่สามารถแก้ปัญหาของฉันได้ ไม่ได้ใช้กระบอกเลย
Michael Laffargue

21

ฉันยังพบสิ่งนี้โดยการฉีดบริการ A เข้าสู่บริการ B และในทางกลับกัน

ฉันคิดว่ามันเป็นสิ่งที่ดีที่ว่านี้ล้มเหลวอย่างรวดเร็วเท่าที่ควรอาจจะหลีกเลี่ยงได้อยู่แล้ว หากคุณต้องการให้บริการของคุณเป็นแบบแยกส่วนและใช้งานได้ดีที่สุดก็ควรหลีกเลี่ยงการอ้างอิงแบบวงกลมให้มากที่สุด โพสต์นี้จะเน้นข้อผิดพลาดที่อยู่รอบ ๆ

ดังนั้นฉันมีคำแนะนำต่อไปนี้:

  • ถ้าคุณรู้สึกว่าการเรียนจะมีปฏิสัมพันธ์บ่อยเกินไป (ฉันพูดคุยเกี่ยวกับคุณลักษณะอิจฉา ), คุณอาจต้องการที่จะต้องพิจารณาการรวม 2 บริการแบ่งออกเป็น 1 ชั้น
  • หากสิ่งที่กล่าวมาข้างต้นไม่ได้ผลสำหรับคุณให้พิจารณาใช้บริการที่ 3 ( EventService) ซึ่งบริการทั้งสองนี้สามารถแทรกเพื่อแลกเปลี่ยนข้อความ

1
นี่คือสิ่งที่เกิดขึ้นกับฉันแน่นอนและนี่คือวิธีที่จะไป หากคุณรู้ว่าคุณมีมากกว่าหนึ่งบริการที่ต้องการการอัปเดตให้ใช้ EventService ขยายได้มากขึ้นโดยที่คุณไม่ต้องสงสัยเลยว่าจะต้องเข้าร่วมกิจกรรมเหล่านั้นเมื่อคุณขยายแอปพลิเคชันตามกิจกรรมเหล่านี้
themightybun

17

เพื่อประโยชน์ของผู้ค้นหา; ฉันได้รับข้อผิดพลาดนี้ มันเป็นสัญลักษณ์ @ ที่หายไป

เช่นนี้ก่อให้เกิดCan't resolve all parameters for MyHttpServiceข้อผิดพลาด

Injectable()
export class MyHttpService{
}

การเพิ่ม@สัญลักษณ์ที่หายไปแก้ไขได้

@Injectable()
export class MyHttpService{
}

2
ในกรณีของฉันฉันจะเพิ่มคลาสพิเศษและอินเทอร์เฟซระหว่าง @Injectable และคำจำกัดความของคลาสบริการดังนั้นคลาสบริการจึงไม่ถูกทำเครื่องหมายว่าสามารถฉีดได้อีกต่อไป
Herc

หากคุณลืมมัณฑนากร @Injectable () ในระดับบริการที่ใช้บริการฉีดอื่น ๆ การบริการที่ตกแต่งอย่างไม่เหมาะสมของคุณจะทำให้เกิดข้อผิดพลาดนี้เช่นกัน
I. Buchan


9

ความเป็นไปได้อื่นไม่ได้emitDecoratorMetadataตั้งค่าเป็นจริงใน tsconfig.json

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}

8

คุณได้รับข้อผิดพลาดนี้หากคุณมีบริการAซึ่งขึ้นอยู่กับคุณสมบัติคงที่ / วิธีการให้บริการBและบริการBเองนั้นขึ้นอยู่กับบริการAการฉีดขึ้นอยู่กับรางน้ำ ดังนั้นมันจึงเป็นแบบพึ่งพาอาศัยแบบวงกลมแม้ว่าจะไม่ใช่เพราะคุณสมบัติ / เมธอดเป็นแบบคงที่ อาจเป็นข้อผิดพลาดที่เกิดขึ้นในการทำงานร่วมกับทอท


ฉันเคยมีเมื่อมีการพึ่งพาฟังก์ชั่นที่กำหนดไว้ในไฟล์เดียวกัน แยกมันเป็นไฟล์แยกคงที่
Joe

1
ขอบคุณที่พูดถึงมัน ฉันพบว่าตัวเองอยู่ในสถานการณ์ที่แน่นอน ฉันไม่ได้ตระหนักว่าการเข้าถึงคลาสสแตติกโดยตรงสามารถมีส่วนเกี่ยวข้องกับ DI ได้ ฉันมีรูปแบบนี้: A -> Bและทั้งคู่ใช้คลาสคงที่เดียวกัน วิธีแก้ปัญหาด้วยความforwardRefช่วยเหลือ แต่ฉันจะดูว่ามันสามารถแก้ปัญหาได้ไหม ฉันอาจจะลองใช้บริการจริงจากคลาสคงที่นี้ (ซึ่งจะนำไปสู่การออกแบบที่ดีขึ้นเช่นกัน)
Slava Fomin II

8

นอกจาก@Injectable()มัณฑนากรที่ขาดหายไปแล้ว

@Injectable()มัณฑนากรที่หายไปในคลาสนามธรรมผลิตไม่สามารถแก้ไขพารามิเตอร์ทั้งหมดสำหรับการให้บริการ: (?) มัณฑนากรต้องอยู่ในMyServiceเช่นเดียวกับในชั้นเรียนที่ได้รับBaseService

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

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

7

ในกรณีของฉันมันเกิดขึ้นเพราะฉันไม่ได้ประกาศประเภทของพารามิเตอร์คอนสตรัคเตอร์

ฉันมีสิ่งนี้:

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

แล้วเปลี่ยนเป็นรหัสด้านล่างแก้ปัญหาของฉัน

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

5

สำหรับฉันมันแค่ขาด()ใน @Injectable ที่เหมาะสมคือ @Injectable ()


หรือในกรณีของฉันลบ @
TDP

4

การเอาพารามิเตอร์ออกจาก constructor แบบฉีดได้ () สามารถแก้ไขได้ในกรณีของฉัน


นี่คือปัญหาของฉันเช่นกัน ฉันมาโพสต์ แต่พบว่าคุณทำก่อน! +1
aesede

จากนั้นจะส่งพารามิเตอร์ไปยังบริการที่สามารถใช้ซ้ำได้อย่างไร
3gwebtrain

4

ในกรณีของฉันมันเป็นเพราะปลั๊กอิน Augury ปิดการใช้งานมันจะทำงานได้ดี ตัวเลือกอื่นคือ aot ก็ใช้ได้เช่นกัน

เครดิตทั้งหมดไปที่ @ Boboss74 เขาโพสต์คำตอบที่นี่: https://github.com/angular/angular/angular/issues/23958


2

สำหรับฉันแล้วปัญหาก็ยิ่งน่ารำคาญฉันใช้บริการภายในบริการและลืมที่จะเพิ่มมันเป็นการพึ่งพาใน appModule! หวังว่านี่จะช่วยให้ใครบางคนประหยัดเวลาหลายชั่วโมงในการทำลายแอปลงเพื่อสร้างแอปอีกครั้ง


1
ฉันเพิ่งขาด@Injectคำอธิบายประกอบ ฉันมองเห็นอย่างชัดเจนว่าข้อความแสดงข้อผิดพลาดพูดถึงอะไรบ้าง หากคุณไม่สงสัยการขึ้นต่อกันแบบวงกลมให้ไปที่คลาสที่กล่าวถึงในข้อผิดพลาดและดูพารามิเตอร์คอนสตรัคเตอร์ทั้งหมดและสมาชิกคลาสใด ๆ ที่ใส่หมายเหตุประกอบไว้@Injectและตรวจสอบให้แน่ใจว่าคุณทำ DI ทั้งหมด เพิ่มเติมเกี่ยวกับ DI ที่นี่: angular.io/docs/ts/latest/guide/dependency-injection.html
Alexander Taylor

2

คุณต้องเพิ่ม Array Provider ใน @Component decorator หรือในโมดูลที่มีการประกาศส่วนประกอบของคุณ ส่วนประกอบภายในที่คุณสามารถทำได้ดังนี้:

@Component({
  moduleId: module.id,
  selector: 'pm-header',
  templateUrl: 'header.component.html',
  styleUrls: ['header.component.css'],
  directives: [ROUTER_DIRECTIVES, NgClass],
  providers: [MobileService]
})

2

ในกรณีของฉันที่ส่งพารามิเตอร์ที่ไม่ถูกต้องไปยังตัวสร้างสร้างข้อผิดพลาดแนวคิดพื้นฐานเกี่ยวกับข้อผิดพลาดนี้คือคุณส่งค่า args ผิดไปยังฟังก์ชันใด ๆ โดยไม่รู้ตัว

export class ProductComponent {
    productList: Array<Product>;

    constructor(productList:Product) { 
         // productList:Product this arg was causing error of unresolved parameters.
         this.productList = [];
    }
}

ฉันแก้ไขได้โดยเพียงแค่ลบอาร์กิวเมนต์นั้น


2

สำหรับฉันฉันได้รับข้อผิดพลาดนี้เมื่อฉันปิดใช้งานการนำเข้านี้ในไฟล์ polyfills.ts โดยไม่ตั้งใจคุณต้องตรวจสอบให้แน่ใจว่ามีการนำเข้านั้นเพื่อหลีกเลี่ยงข้อผิดพลาดนั้น

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

2

ในกรณีของฉันฉันพยายามขยายวิธี " NativeDateAdapter" เพื่อแทนที่ " format(date: Date, displayFormat: Object)"

ใน AngularMaterial-2 DatePicker

โดยพื้นฐานแล้วฉันลืมเพิ่มคำ@Injectableอธิบายประกอบ

หลังจากฉันเพิ่มสิ่งนี้ไปยังคลาส "CustomDateAdapter" ของฉัน:

@Injectable({
  providedIn: 'root'
})

ข้อผิดพลาดได้หายไป


สิ่งนี้ใช้ได้สำหรับฉัน แต่ฉันไม่รู้ว่าทำไม ทั้งบริการและส่วนประกอบที่ได้รับผ่าน DI จำเป็นต้องระบุไว้ใน: root เพื่อให้ DI ทำงานได้หรือไม่
Mike Furlender

2

คำตอบนี้อาจมีประโยชน์มากสำหรับปัญหานี้ นอกจากนี้สำหรับกรณีของฉันให้ส่งออกบริการเป็นdefaultสาเหตุ

ไม่ถูกต้อง:

@Inject()
export default class MobileService { ... }

แก้ไข:

@Inject()
export class MobileService { ... }

2

นี่อาจเป็นปัญหาที่ยากมากในการดีบักเนื่องจากไม่มีข้อเสนอแนะในข้อผิดพลาด หากคุณกังวลเกี่ยวกับการขึ้นต่อกันตามวัฏจักรจริงนี่คือสิ่งที่สำคัญที่สุดที่จะดูใน stack trace a) ชื่อของบริการ b) พารามิเตอร์ Constructor ในบริการนั้นที่มีเครื่องหมายคำถามเช่นถ้ามันเป็นเช่นนี้:

ไม่สามารถแก้ไขพารามิเตอร์ทั้งหมดสำหรับ AuthService: ([วัตถุวัตถุ], [วัตถุวัตถุ], [วัตถุวัตถุ], [วัตถุวัตถุ],?)

หมายความว่าพารามิเตอร์ที่ 5 เป็นบริการที่ขึ้นอยู่กับ AuthService ด้วย เช่นเครื่องหมายคำถามหมายความว่าไม่ได้รับการแก้ไขโดย DI

จากนั้นคุณเพียงแค่ต้องแยกบริการทั้งสองออกโดยการปรับโครงสร้างรหัส


1

ฉันพบข้อผิดพลาดนี้โดยพิมพ์ชื่อบริการผิดเช่นตัวสร้าง (ส่วนตัวmyService: MyService )

สำหรับบริการที่สะกดผิดฉันสามารถตรวจสอบว่าบริการใดเป็นปัญหา (ฉันมีหลายรายชื่ออยู่ในตัวสร้าง) โดยตรวจสอบหน้าใน Chrome-> Console คุณจะเห็นเป็นส่วนหนึ่งของข้อความที่เป็นรายการ "พารามิเตอร์" อาร์เรย์โดยการแสดงวัตถุวัตถุวัตถุวัตถุ? (หรืออะไรทำนองนั้น) สังเกตเห็นว่า "?" เป็นและนั่นคือตำแหน่งของการบริการที่เป็นสาเหตุของปัญหา


1

แม้ว่าอาจมีการกล่าวถึงลำดับของคลาสที่ส่งออกจากภายในบาร์เรล แต่สถานการณ์ต่อไปนี้อาจให้ผลเหมือนกัน

สมมติว่าคุณมีชั้นเรียนA, BและCการส่งออกจากภายในไฟล์เดียวกันที่Aขึ้นอยู่กับBและC:

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

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

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

เนื่องจากคลาสที่ต้องพึ่งพา (เช่นในคลาสของกรณีนี้BและC) ยังไม่เป็นที่รู้จักสำหรับแองกูลาร์ ( อาจเป็นที่รันไทม์ในระหว่างกระบวนการฉีดขึ้นรูปของแองกูลาร์ในคลาสA ) ข้อผิดพลาดถูกยกขึ้น

สารละลาย

วิธีแก้ปัญหาคือการประกาศและส่งออกคลาสที่ต้องพึ่งพาก่อนที่คลาสจะทำ DI

เช่นในกรณีข้างต้นคลาสAจะประกาศทันทีหลังจากการอ้างอิงของมันถูกกำหนด:

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

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

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

1

ในกรณีของฉันฉันส่งออกคลาสและ Enum จากไฟล์คอมโพเนนต์เดียวกัน:

mComponent.component.ts:

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

จากนั้นผมก็พยายามที่จะใช้จากลูกของMyEnum MyComponentClassนั่นเป็นสาเหตุของข้อผิดพลาดไม่สามารถแก้ไขพารามิเตอร์ทั้งหมดได้

ด้วยการย้ายMyEnumในโฟลเดอร์แยกต่างหากMyComponentClassนั่นช่วยแก้ไขปัญหาของฉันได้!

ดังที่GünterZöchbauerกล่าวถึงสิ่งนี้เกิดขึ้นเนื่องจากการบริการหรือส่วนประกอบขึ้นอยู่กับการเวียน


1

หากบริการของคุณถูกกำหนดในไฟล์เดียวกับส่วนประกอบ (ที่ใช้งาน) และบริการจะถูกกำหนดหลังจากส่วนประกอบในไฟล์คุณอาจได้รับข้อผิดพลาดนี้ นี่เป็นเพราะปัญหา 'forwardRef' เดียวกันที่คนอื่น ๆ ได้กล่าวถึง ในขณะนี้ VSCode ไม่ค่อยดีนักในการแสดงข้อผิดพลาดนี้และคอมไพล์การคอมไพล์สำเร็จ

การรันบิลด์ด้วย--aotสามารถปกปิดปัญหานี้ได้เนื่องจากวิธีการทำงานของคอมไพเลอร์ (อาจเกี่ยวข้องกับการเขย่าต้นไม้)

การแก้ไข:ตรวจสอบให้แน่ใจว่ามีการกำหนดบริการในไฟล์อื่นหรือก่อนที่จะกำหนดองค์ประกอบ (ฉันไม่แน่ใจว่าสามารถใช้ forwardRef ในกรณีนี้ได้หรือไม่ แต่ดูเหมือนว่าจะทำเช่นนั้น)

ถ้าฉันมีบริการที่ง่ายมากซึ่งเชื่อมโยงกับส่วนประกอบอย่างมาก (เรียงลำดับเหมือนโมเดลมุมมอง) - เช่น ImageCarouselComponentฉันอาจตั้งชื่อมันImageCarouselComponent.service.tsเพื่อไม่ให้สับสนกับบริการอื่น ๆ ของฉัน


1

ในกรณีของฉันมันคือการอ้างอิงแบบวงกลม ฉันมี MyService โทร Myservice2 และ MyService2 เรียก MyService

ไม่ดี :(


1

ในกรณีของฉันเหตุผลดังต่อไปนี้:

  • บริการฉีดของฉัน A ขยายอีกคลาส B
  • B มีนวกรรมิกซึ่งต้องการอาร์กิวเมนต์
  • ฉันไม่ได้กำหนดคอนสตรัคเตอร์ใด ๆ ใน A

ดังนั้นเมื่อพยายามสร้างวัตถุ A คอนสตรัคเตอร์เริ่มต้นจึงล้มเหลว ฉันไม่รู้ว่าทำไมนี่ไม่ใช่ข้อผิดพลาดในการรวบรวม

ฉันได้รับการแก้ไขโดยเพิ่มตัวสร้างใน A ซึ่งเรียกว่าตัวสร้างของ B อย่างถูกต้อง


1

Gotcha!

หากไม่มีคำตอบข้างต้นช่วยคุณได้บางทีคุณอาจนำเข้าองค์ประกอบบางอย่างจากไฟล์เดียวกันที่มีส่วนประกอบกำลังฉีดบริการ

ฉันอธิบายได้ดีกว่า:

นี่คือไฟล์บริการ:

// your-service-file.ts
import { helloWorld } from 'your-component-file.ts'

@Injectable()
export class CustomService() {
  helloWorld()
}

นี่คือไฟล์คอมโพเนนต์:

@Component({..})
export class CustomComponent {
  constructor(service: CustomService) { }
}

export function helloWorld() {
  console.log('hello world');
}

ดังนั้นมันจึงทำให้เกิดปัญหาแม้ว่าสัญลักษณ์ไม่ได้อยู่ในองค์ประกอบเดียวกัน แต่อยู่ในไฟล์เดียวกัน ย้ายสัญลักษณ์ (อาจเป็นฟังก์ชั่นค่าคงที่คลาสและอื่น ๆ ... ) ที่อื่นและข้อผิดพลาดจะจางหายไป


1

สำหรับรุ่นเชิงมุม 6 และใหม่กว่าให้ลอง

@Injectable({
  providedIn: 'root'
})

.. อยู่เหนือระดับบริการของคุณโดยไม่มีบรรทัดอื่น ๆ อยู่ระหว่างกลาง

ข้อได้เปรียบ

  • ไม่จำเป็นต้องเพิ่มบริการลงในโมดูลใด ๆ (จะเป็น "ค้นพบอัตโนมัติ")
  • บริการจะเป็นแบบซิงเกิล (เนื่องจากจะถูกฉีดเข้าไปในรูท)

[ เอกสารเชิงมุม ]

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.