typescript - Lỗi khi cố gắng tiêm một dịch vụ vào một component Angular "EXCEPTION: Không thể giải quyết tất cả các tham số cho component", tại sao?
Tôi đã xây dựng một ứng dụng cơ bản trong Angular, nhưng tôi đã gặp phải một vấn đề kỳ lạ khi tôi không thể tiêm một service vào một trong các component của mình. Tuy nhiên, service lại tiêm bình thường vào bất kỳ ba component khác mà tôi đã tạo.
Trước hết, đây là dịch vụ:
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;
}
}
Và thành phần mà nó từ chối làm việc cùng:
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);
}
}
Lỗi mà tôi nhận được trong bảng điều khiển trình duyệt là:
NGOẠI LỆ: Không thể giải quyết tất cả các tham số cho HeaderComponent: (?).
Tôi có dịch vụ trong hàm bootstrap nên nó có một nhà cung cấp. Và dường như tôi có thể tiêm nó vào constructor của bất kỳ component nào khác của tôi mà không gặp vấn đề gì.
Câu trả lời #1
Nhập nó từ tệp nơi nó được khai báo trực tiếp thay vì từ barrel.
Tôi không biết chính xác điều gì gây ra vấn đề nhưng tôi đã thấy nó được đề cập nhiều lần (có lẽ là một dạng phụ thuộc vòng).
Nó cũng nên có thể sửa được bằng cách thay đổi thứ tự các xuất khẩu trong barrel (không rõ chi tiết, nhưng cũng đã được đề cập)
Câu trả lời #2
Ngoài các câu trả lời trước đã đưa ra, có vẻ lỗi này cũng xảy ra khi dịch vụ có thể tiêm của bạn thiếu trình trang trí @Injectable() thực sự. Vì vậy, trước khi bạn gỡ lỗi vấn đề phụ thuộc tuần hoàn và thứ tự các import/export của mình, hãy kiểm tra đơn giản xem dịch vụ của bạn có thực sự được định nghĩa @Injectable() hay không.
Điều này áp dụng cho phiên bản Angular mới nhất hiện tại, Angular 2.1.0.
Tôi đã mở một vấn đề về việc này.
Câu trả lời số 3
Tính đến Angular 2.2.3, hiện đã có một hàm tiện ích forwardRef() cho phép bạn tiêm các nhà cung cấp chưa được định nghĩa.
Bằng cách không được định nghĩa, ý tôi là bản đồ tiêm phụ thuộc không biết định danh. Điều này xảy ra trong các phụ thuộc vòng tròn. Bạn có thể có các phụ thuộc vòng tròn trong Angular mà rất khó để gỡ rối và nhìn thấy.
export class HeaderComponent {
mobileNav: boolean = false;
constructor(@Inject(forwardRef(() => MobileService)) public ms: MobileService) {
console.log(ms);
}
}
Thêm @Inject(forwardRef(() => MobileService)) vào tham số của hàm dựng trong mã nguồn của câu hỏi gốc sẽ khắc phục được vấn đề.
Tài liệu tham khảo
Hướng dẫn Angular 2: ForwardRef
Tham chiếu tiến trong Angular 2
Câu trả lời số 4
SAI #1: Quên Decorator:
//Uncaught Error: Can't resolve all parameters for MyFooService: (?).
export class MyFooService { ... }
SAI #2: Bỏ qua ký hiệu "@":
//Uncaught Error: Can't resolve all parameters for MyFooService: (?).
Injectable()
export class MyFooService { ... }
SAI #3: Bỏ qua ký hiệu "()"
//Uncaught Error: Can't resolve all parameters for TypeDecorator: (?).
@Injectable
export class MyFooService { ... }
SAI #4: Chữ "i" viết thường:
//Uncaught ReferenceError: injectable is not defined
@injectable
export class MyFooService { ... }
SAI #5: Bạn đã quên: import { Injectable } từ '@angular/core';
//Uncaught ReferenceError: Injectable is not defined
@Injectable
export class MyFooService { ... }
ĐÚNG:
@Injectable()
export class MyFooService { ... }
Câu trả lời #5
Như đã nêu, vấn đề được gây ra bởi thứ tự xuất khẩu trong barrel, điều này là do các phụ thuộc vòng tròn.
Giải thích chi tiết hơn có ở đây: https://stackoverflow.com/a/37907696/893630
Câu trả lời #6
Tôi cũng gặp phải điều này khi tiêm dịch vụ A vào dịch vụ B và ngược lại.
Tôi nghĩ rằng điều này thất bại nhanh là điều tốt vì nó có lẽ nên được tránh dù sao. Nếu bạn muốn các dịch vụ của mình trở nên mô-đun hơn và có thể tái sử dụng, tốt nhất là nên tránh các tham chiếu tuần hoàn càng nhiều càng tốt. Bài viết này nêu bật những cạm bẫy xung quanh vấn đề đó.
Do đó, tôi có các đề xuất sau:
- Nếu bạn cảm thấy các lớp đang tương tác quá thường xuyên (tôi đang nói về ham muốn tính năng), bạn có thể muốn cân nhắc gộp 2 dịch vụ thành 1 lớp.
- Nếu những điều trên không hiệu quả với bạn, hãy xem xét sử dụng một dịch vụ thứ 3, (một
EventService) mà cả hai dịch vụ có thể tiêm vào để trao đổi tin nhắn.
Câu trả lời số 7
Vì lợi ích của những người tìm kiếm; tôi đã gặp lỗi này. Đơn giản là thiếu ký hiệu @.
Tức là. Điều này tạo ra lỗi Không thể giải quyết tất cả các tham số cho MyHttpService.
Injectable()
export class MyHttpService{
}
Thêm ký hiệu @ còn thiếu sẽ khắc phục được nó.
@Injectable()
export class MyHttpService{
}
Câu trả lời #8
Một khả năng khác là không đặt emitDecoratorMetadata thành true trong tsconfig.json
{
"compilerOptions": {
...
"emitDecoratorMetadata": true,
...
}
}
Câu trả lời số 9
Trong trường hợp của tôi, tôi cần thêm import "core-js/es7/reflect"; vào ứng dụng của mình để @Injectable hoạt động.
Câu trả lời số 10
Ngoài việc thiếu bộ trang trí @Injectable()
Thiếu decorator @Injectable() trong lớp trừu tượng đã tạo ra lỗi Can't resolve all parameters for service: (?). Decorator cần có trong MyService cũng như trong lớp dẫn xuất BaseService
//abstract class
@Injectable()
abstract class BaseService { ... }
//MyService
@Injectable()
export class MyService extends BaseService {
.....
}
Câu trả lời số 11
Bạn sẽ gặp lỗi này nếu bạn có dịch vụ A phụ thuộc vào một thuộc tính/phương thức tĩnh của dịch vụ B và chính dịch vụ B lại phụ thuộc vào dịch vụ A thông qua tiêm phụ thuộc. Vậy nên đây có thể coi là một dạng phụ thuộc vòng, mặc dù thực ra không phải vì thuộc tính/phương thức là tĩnh. Có thể là một lỗi xảy ra khi kết hợp với AOT.
Câu trả lời #12
Trong trường hợp của tôi, điều đó xảy ra vì tôi đã không khai báo kiểu cho một tham số của constructor.
Tôi đã có một cái gì đó như thế này:
constructor(private URL, private http: Http) { }
và sau đó thay đổi nó thành mã dưới đây đã giải quyết vấn đề của tôi.
constructor(private URL : string, private http: Http) {}
