PENGECUALIAN: Tidak dapat menyelesaikan semua parameter


431

Saya telah membangun aplikasi dasar di Angular 2, tetapi saya telah menemukan masalah aneh di mana saya tidak dapat menyuntikkan layanan ke salah satu komponen saya. Ini menyuntikkan dengan baik ke salah satu dari tiga komponen lain yang telah saya buat.

Sebagai permulaan, ini adalah layanan:

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

}

Dan komponen yang menolak untuk bekerja dengannya:

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

}

Kesalahan yang saya dapatkan di konsol browser adalah ini:

PENGECUALIAN: Tidak dapat menyelesaikan semua parameter untuk HeaderComponent: (?).

Saya memiliki layanan dalam fungsi bootstrap sehingga ia memiliki penyedia. Dan saya tampaknya dapat menyuntikkannya ke dalam konstruktor komponen saya yang lain tanpa masalah.


14
Mungkin impor? Apakah '../'sebuah index.ts(Barrel)? Bisakah Anda mencoba mengimpornya dari file yang dideklarasikan langsung?
Günter Zöchbauer

Ajaibnya yang tampaknya telah memperbaikinya! Aneh bahwa itu tidak akan berfungsi menggunakan laras ketika komponen lain yang saya uji layanannya melakukannya. Jika Anda ingin memposting itu sebagai jawaban, bukan komentar, saya akan menerimanya.
Keith Otto

11
Umumnya ketergantungan melingkar.
Gary

Saya punya masalah dengan ketergantungan melingkar juga. Perlu dicatat bahwa versi yang lebih baru dari paket web jauh lebih baik dalam memberi tahu Anda hal ini
Enn

Sepertinya ketergantungan melingkar, Jika Anda menggunakan sudut> = 4 sehingga Anda dapat menyingkirkan intex.ts (barel) dan mengimpor semua yang Anda butuhkan secara langsung.
Rammgarot

Jawaban:


457

Impor dari file yang dinyatakan langsung bukan pada laras.

Saya tidak tahu persis apa yang menyebabkan masalah ini tetapi saya melihatnya beberapa kali (mungkin semacam ketergantungan sirkuler).

Itu juga harus diperbaiki dengan mengubah urutan ekspor dalam barel (tidak tahu detail, tetapi disebutkan juga)


16
ini benar jika misalnya Anda memiliki layanan yang disuntikkan ke layanan lain yang pertama harus didahulukan dalam tong.
Joao Garin

17
Tim Angular2 tidak merekomendasikan barel lagi karena banyak masalah seperti itu. Senang mendengar saya dapat membantu :)
Günter Zöchbauer

13
Tidak tahu bahwa tim Angular 2 tidak merekomendasikan barel. Jika demikian, mereka harus mencatat bahwa dalam glosarium yang membahas manfaatnya. Dan proyek-proyek seperti angular2-webpack-starter tidak boleh menggunakannya.
Biru

3
Tampaknya ini diperbaiki (bukan masalah di 2.0.2). Saya menemukan barel masih berguna, khususnya ketika saya perlu mengimpor beberapa model dan layanan antara modul yang berbeda. Ini import { cleanValues, getState, FirebaseService, NotificationService, ... } from '../../shared/services';adalah rasa sakit ketika tidak berhasil (; NgModuleada bantuan dengan layanan singleton ...
Sasxa

3
Argghh Saya menyelesaikannya dengan mengubah urutan ekspor dalam file barrel (index.ts) .. terima kasih banyak
Spock

331

Selain jawaban sebelumnya yang diberikan, tampaknya kesalahan ini juga terjadi ketika layanan injeksi Anda tidak ada @Injectable() dekorator yang . Jadi sebelum Anda men-debug hal ketergantungan siklik dan urutan impor / ekspor Anda, lakukan pemeriksaan sederhana apakah layanan Anda benar-benar telah @Injectable()ditentukan.

Ini berlaku untuk Angular terbaru saat ini, Angular 2.1.0.

Saya membuka masalah tentang hal ini .


Ya kesalahan ini biasanya karena Anda lupa menambahkan @Injectable dan misalnya Anda mungkin hanya mengimpor Routerdari '@ angular / router' dan tanpa injeksi itu, kesalahan ini akan selalu terjadi (segera setelah Anda memutuskan untuk membuat satu baris dari penggunaan kode router yang disuntikkan
Eric Bishard

Jawaban yang luar biasa, masalah saya adalah saya menambahkan metode dalam layanan saya dan tidak menambahkan titik koma setelah penjepit terakhir. Saya tidak tahu mengapa harus seperti ini, tetapi itu tidak terjadi di kelas komponen ... untuk saat ini saya senang untuk pindah!
egimaben

Saya punya model sederhana yang memberi saya kesalahan ini. Saya menggunakan pintasan tempat Anda membuat properti di konstruktor model. Jenis-jenis properti itu hanya string dan int. Lalu tiba-tiba masalah ini mulai terjadi. Menambahkan @Injectable () memperbaiki masalah ini. Aneh karena tidak ada model saya yang lain yang memiliki Injectable ditambahkan. Saya harus menambahkan bahwa saya memutakhirkan beberapa perpustakaan sebelum menambahkan model baru ini. Mungkin ada hubungannya dengan itu, tetapi bekerja sekarang. Terima kasih.
Moutono

@Outono Benar. Dengan konstruktor kosong di layanan Anda, injeksi dependensi tampaknya tidak dipicu dan @injectable()tidak diperlukan. Yang merupakan keanehan lain pada dirinya sendiri. Untuk ukuran yang baik saya masih menambahkannya, hanya ketika Anda harus memutuskan untuk menyuntikkan sesuatu.
JP ten Berge

Ingatlah bahwa jika layanan Anda memiliki kelas dasar yang juga perlu didekorasi dengan @Injectable ()
Sam Shiles

110

Pada Angular 2.2.3sekarang ada forwardRef()fungsi utilitas yang memungkinkan Anda untuk menyuntikkan penyedia yang belum ditentukan.

Dengan tidak didefinisikan, maksud saya bahwa peta injeksi ketergantungan tidak tahu pengenal. Inilah yang terjadi selama dependensi melingkar. Anda dapat memiliki dependensi melingkar dalam Angular yang sangat sulit untuk dilepaskan dan dilihat.

export class HeaderComponent {
  mobileNav: boolean = false;

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

}

Menambahkan @Inject(forwardRef(() => MobileService))ke parameter konstruktor dalam kode sumber pertanyaan asli akan memperbaiki masalah.

Referensi

Manual Angular 2: ForwardRef

Teruskan referensi dalam Angular 2


3
forwardRef()sudah ada di alpha ;-) Ini hanya diperlukan jika Mobilelayanan dinyatakan lebih jauh di file yang sama. Jika kelas ada di file yang berbeda, tidak perluforwardRef()
Günter Zöchbauer

4
Günter Zöchbauer, saya masih berusaha mencari tahu masalah sebenarnya dengan kode saya, tetapi sementara forwardRef()itu membantu menghilangkan Can't resolve all parameters for ...pesan tersebut. Setidaknya komponen berfungsi saat saya mencari solusi yang lebih baik untuk masalah ini. (Dan ya, dependensi gagal diimpor langsung dari file-nya)
Nik

4
@ GünterZöchbauer Saya telah memperbarui jawaban saya dengan referensi. Saya tidak mencoba mengambil dari jawaban Anda, tetapi ini sebenarnya memecahkan masalah dan orang-orang perlu mengetahuinya. Jika Anda mencari di Google pertanyaan tidak ada hasil yang mengatakan untuk digunakan forwardRef. Sangat sulit ditemukan. Butuh saya sepanjang hari kemarin untuk menyelesaikan masalah ini.
Reactgular

Aneh. Saya memposting setidaknya selusin jawaban yang menyarankan menggunakan foreardRefdiri saya tetapi tidak lagi setelah NgModulediperkenalkan. Saya tidak khawatir kehilangan repetisi. Saya hanya ingin tahu mengapa Anda mengalami ini setelah ini tidak muncul lagi sejak beberapa bulan. Saya akan melihat lebih dekat ketika saya kembali ke rumah dalam beberapa hari. Terima kasih banyak atas umpan baliknya.
Günter Zöchbauer

2
Jika seseorang juga tersesat tentang impor: impor {Komponen, Suntikkan, ForwardRefFn, forwardRef} dari '@ angular / core';
Natanael

69

SALAH # 1: Lupa Penghias:

//Uncaught Error: Can't resolve all parameters for MyFooService: (?).
export class MyFooService { ... }

SALAH # 2: Menghilangkan Simbol "@":

//Uncaught Error: Can't resolve all parameters for MyFooService: (?).
Injectable()
export class MyFooService { ... }

SALAH # 3: Menghilangkan Simbol "()":

//Uncaught Error: Can't resolve all parameters for TypeDecorator: (?).
@Injectable
export class MyFooService { ... }

SALAH # 4: Huruf kecil "i":

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

SALAH # 5: Anda lupa: impor {injectable} dari '@ angular / core';

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

BENAR:

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


21

Saya juga mengalami ini dengan menyuntikkan layanan A ke layanan B dan sebaliknya.

Saya pikir ini hal yang baik bahwa ini gagal dengan cepat karena mungkin harus dihindari . Jika Anda ingin layanan Anda menjadi lebih modular dan dapat digunakan kembali, yang terbaik adalah menghindari referensi melingkar sebanyak mungkin. Posting ini menyoroti jebakan di sekitarnya.

Karena itu, saya memiliki rekomendasi berikut:

  • Jika Anda merasa kelas terlalu sering berinteraksi (saya berbicara tentang iri fitur ), Anda mungkin ingin mempertimbangkan menggabungkan 2 layanan menjadi 1 kelas .
  • Jika hal di atas tidak bekerja untuk Anda, pertimbangkan untuk menggunakan layanan ke - 3 , (an EventService) yang dapat disuntikkan oleh kedua layanan untuk bertukar pesan.

1
Ini pasti apa yang terjadi pada saya, dan ini adalah cara untuk pergi. Jika Anda tahu Anda memiliki lebih dari satu layanan yang membutuhkan pembaruan, gunakan EventService. Ini lebih dapat diperluas karena Anda tidak perlu ragu untuk memanfaatkan acara tersebut saat Anda memperpanjang aplikasi berdasarkan peristiwa ini.
themightybun

17

Untuk kepentingan pencari; Saya mendapat kesalahan ini. Itu hanya simbol @ yang hilang.

Yaitu ini menghasilkan Can't resolve all parameters for MyHttpServicekesalahan.

Injectable()
export class MyHttpService{
}

Menambahkan @simbol yang hilang akan memperbaikinya.

@Injectable()
export class MyHttpService{
}

2
Dalam kasus saya, saya telah menambahkan kelas dan antarmuka tambahan antara @Injectable dan definisi kelas layanan, sehingga kelas layanan tidak lagi ditandai sebagai injeksi.
Herc

Jika Anda benar-benar lupa dengan dekorator @Injectable () pada kelas layanan yang menggunakan layanan injeksi lainnya, maka layanan Anda yang didekorasi dengan tidak tepat juga akan membuang kesalahan ini.
I. Buchan

10

Dalam kasus saya, saya perlu menambahkan import "core-js/es7/reflect";aplikasi saya untuk membuat @Injectablepekerjaan.


9

Kemungkinan lain adalah tidak emitDecoratorMetadatadisetel ke true di tsconfig.json

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}

8

Anda mendapatkan kesalahan ini jika Anda memiliki layanan A yang tergantung pada properti statis / metode layanan B dan layanan B itu sendiri tergantung pada layanan A melalui injeksi ketergantungan. Jadi itu semacam ketergantungan melingkar, meskipun bukan karena properti / metode statis. Mungkin bug yang terjadi dalam kombinasi dengan AOT .


Saya juga sudah memilikinya ketika ada ketergantungan pada fungsi yang didefinisikan dalam file yang sama. Membagi menjadi file terpisah memperbaikinya.
Joe

1
Terima kasih telah menyebutkannya. Saya menemukan diri saya dalam situasi yang tepat. Saya tidak menyadari bahwa mengakses kelas statis secara langsung dapat ada hubungannya dengan DI. Saya memiliki skema ini: A -> Bdan keduanya menggunakan kelas statis yang sama. Solusi dengan forwardRefbantuan, tapi saya akan melihat bagaimana ini bisa diuraikan. Saya mungkin akan mencoba membuat layanan nyata dari kelas statis ini (ini akan mengarah pada desain yang lebih baik juga).
Slava Fomin II

8

Selain @Injectable()dekorator yang hilang

@Injectable()Dekorator yang hilang di kelas abstrak menghasilkan Tidak bisa menyelesaikan semua parameter untuk layanan: (?) Dekorator harus ada di dalam MyServicemaupun di kelas turunanBaseService

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

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

7

Dalam kasus saya, itu terjadi karena saya tidak mendeklarasikan tipe untuk parameter konstruktor.

Saya punya sesuatu seperti ini:

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

dan kemudian mengubahnya ke kode di bawah ini memecahkan masalah saya.

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

5

bagi saya itu hanya kekurangan ()di @Injectable. Proper adalah @Injectable ()


Atau dalam kasus saya secara tidak sengaja menghapus @
TDP

4

Menghapus parameter dari metode konstruktor () yang dapat dipecahkan menyelesaikannya untuk kasus saya.


Ini juga masalah saya. Saya datang untuk mempostingnya tetapi ternyata Anda melakukannya lebih dulu! +1
aesede

lalu bagaimana cara mengirim parameter ke layanan yang dapat digunakan kembali?
3gwebtrain


2

Bagi saya masalahnya lebih menyebalkan, saya menggunakan layanan di dalam layanan dan lupa menambahkannya sebagai ketergantungan pada appModule! Semoga ini membantu seseorang menghemat beberapa jam memecah aplikasi hanya untuk membangunnya kembali


1
Saya baru saja melewatkan @Injectanotasi. Saya mengabaikan apa yang dikatakan pesan kesalahan itu sedikit. Jika Anda tidak mencurigai dependensi melingkar, buka saja kelas yang disebutkan dalam kesalahan dan lihat semua parameter konstruktor dan setiap anggota kelas yang dianotasi dengan @Injectdan pastikan Anda melakukan DI dengan benar pada semuanya. Lebih lanjut tentang DI di sini: angular.io/docs/ts/latest/guide/dependency-injection.html
Alexander Taylor

2

Anda harus menambahkan array penyedia di dekorator @Component atau dalam modul tempat komponen Anda dideklarasikan. Di dalam komponen Anda dapat melakukan seperti di bawah ini:

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

2

Dalam kasus saya melewatkan parameter yang salah ke konstruktor menghasilkan kesalahan ini, ide dasar tentang kesalahan ini adalah bahwa Anda tanpa sadar melewati beberapa argumen salah untuk fungsi apa pun.

export class ProductComponent {
    productList: Array<Product>;

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

Saya memecahkan ini dengan hanya menghapus argumen itu.


2

Bagi saya, saya mendapatkan kesalahan ini ketika saya keliru menonaktifkan impor ini dalam file polyfills.ts, Anda harus memastikan itu diimpor untuk menghindari kesalahan itu.

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

Dalam kasus saya, saya mencoba memperluas " NativeDateAdapter" untuk mengganti format(date: Date, displayFormat: Object)metode " ".

Di AngularMaterial-2 DatePicker.

Jadi pada dasarnya saya lupa menambahkan @Injectableanotasi.

Setelah saya menambahkan ini ke kelas "CustomDateAdapter" saya:

@Injectable({
  providedIn: 'root'
})

Kesalahan telah terjadi.


Ini bekerja untuk saya, tetapi saya tidak tahu mengapa. Apakah layanan dan komponen yang menerimanya melalui DI perlu disediakanIn: root agar DI berfungsi?
Mike Furlender

2

Jawaban ini mungkin sangat membantu untuk masalah ini. Selain itu, untuk kasus saya, mengekspor layanan defaultadalah penyebabnya.

SALAH:

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

BENAR:

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

2

Ini bisa menjadi masalah yang sangat sulit untuk di-debug karena kurangnya umpan balik dalam kesalahan. Jika Anda khawatir tentang ketergantungan siklik yang sebenarnya, berikut adalah hal paling penting untuk dilihat dalam pelacakan tumpukan a) nama layanan b) parameter konstruktor dalam layanan yang memiliki tanda tanya misalnya jika terlihat seperti ini:

tidak dapat menyelesaikan semua parameter untuk AuthService: ([Objek objek], [Objek objek], [Objek objek], [Objek objek],?)

maka itu berarti parameter ke-5 adalah layanan yang juga bergantung pada AuthService. yaitu tanda tanya, berarti itu tidak diselesaikan oleh DI.

Dari sana, Anda hanya perlu memisahkan 2 layanan dengan merestrukturisasi kode.


1

Saya mengalami kesalahan ini dengan salah ketik nama layanan, yaitu konstruktor (private myService: MyService ).

Untuk layanan yang salah eja, saya dapat menentukan layanan mana yang menjadi masalah (saya telah mendaftarkan beberapa di konstruktor) dengan memeriksa halaman di Chrome-> Console. Anda akan melihat sebagai bagian dari pesan daftar array "parameter" dengan menampilkan Object objek, Object object,? (atau semacam itu). Perhatikan di mana "?" adalah dan itu adalah posisi layanan yang menyebabkan masalah.


1

Meskipun pemesanan kelas yang diekspor dari dalam tong mungkin telah disebutkan, skenario berikut ini juga dapat menghasilkan efek yang sama.

Misalkan Anda memiliki kelas A,, Bdan Cdiekspor dari dalam file yang sama di mana Atergantung Bdan C:

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

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

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

Karena kelas dependen (yaitu dalam hal ini kelas Bdan C) belum diketahui oleh Angular, ( mungkin pada saat run-time selama proses injeksi dependensi Angular pada kelasA ) kesalahan meningkat.

Larutan

Solusinya adalah mendeklarasikan dan mengekspor kelas-kelas dependen sebelum kelas di mana DI dilakukan.

yaitu dalam kasus di atas kelas Adideklarasikan tepat setelah dependensinya didefinisikan:

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

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

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

1

Dalam kasus saya, saya mengekspor Kelas dan Enum dari file komponen yang sama:

mComponent.component.ts:

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

Kemudian, saya mencoba menggunakan MyEnumdari seorang anak MyComponentClass. Itu menyebabkan kesalahan Can't diselesaikan semua parameter .

Dengan memindahkan MyEnumfolder terpisah dari MyComponentClass, itu memecahkan masalah saya!

Seperti yang dikatakan Günter Zöchbauer, ini terjadi karena suatu layanan atau komponen tergantung secara melingkar.


1

Jika layanan Anda didefinisikan dalam file yang sama dengan komponen (yang mengkonsumsinya) dan layanan ditentukan setelahnya komponen dalam file Anda mungkin mendapatkan kesalahan ini. Ini karena masalah 'forwardRef' yang sama yang disebutkan orang lain. Saat ini VSCode tidak hebat menunjukkan kesalahan ini dan build berhasil dikompilasi.

Menjalankan build with --aotcan mask masalah ini karena cara kerja kompiler (mungkin terkait dengan pengocokan pohon).

Solusi: Pastikan layanan didefinisikan dalam file lain atau sebelum definisi komponen. (Saya tidak yakin apakah forwardRef dapat digunakan dalam kasus ini, tetapi tampaknya kikuk melakukannya).

Jika saya memiliki layanan yang sangat sederhana yang sangat kuat terkait dengan komponen (semacam model tampilan) - misalnya. ImageCarouselComponent, Saya boleh menamainya ImageCarouselComponent.service.tssehingga tidak ikut campur dengan layanan saya yang lain.


1

Dalam kasus saya itu adalah referensi melingkar. Saya meminta MyService memanggil Myservice2 Dan MyService2 memanggil MyService.

Tidak baik :(


1

Dalam kasus saya, alasannya adalah sebagai berikut:

  • layanan injeksi saya A memperluas kelas lain B
  • B memiliki konstruktor yang membutuhkan argumen
  • Saya belum mendefinisikan konstruktor apa pun di A

Akibatnya, ketika mencoba membuat objek A, konstruktor default gagal. Saya tidak tahu mengapa ini bukan kesalahan kompilasi.

Saya memperbaikinya dengan hanya menambahkan konstruktor di A, yang benar disebut konstruktor B.


1

Kena kau!

Jika tidak ada jawaban di atas yang membantu Anda, mungkin Anda mengimpor beberapa elemen dari file yang sama di mana komponen menyuntikkan layanan.

Saya jelaskan lebih baik:

Ini adalah file layanan :

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

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

Ini adalah file komponen :

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

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

Jadi itu menyebabkan masalah bahkan jika simbol tidak berada di dalam komponen yang sama, tetapi hanya di dalam file yang sama. Pindahkan simbol (bisa berupa fungsi, konstanta, kelas dan sebagainya ...) di tempat lain dan kesalahannya akan hilang


1

untuk versi sudut 6 dan yang lebih baru, coba

@Injectable({
  providedIn: 'root'
})

.. tepat di atas kelas layanan Anda tanpa garis lain di antaranya

keuntungan

  • tidak perlu menambahkan layanan ke modul apa pun (akan "ditemukan secara otomatis")
  • layanan akan menjadi singleton (karena akan disuntikkan ke root)

[ dokumen sudut ]

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.