ChatGPT解决这个技术问题 Extra ChatGPT

尝试将服务注入角度组件时出错“例外:无法解析组件的所有参数”,为什么?

我已经在 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 的所有参数:(?)。

我在引导函数中有服务,所以它有一个提供者。而且我似乎能够毫无问题地将它注入到我的任何其他组件的构造函数中。

也许是进口? '../'index.ts(桶)吗?您可以尝试从直接声明它的文件中导入它吗?
奇迹般地,这似乎已经解决了它!奇怪的是,当我使用其他组件测试服务时,它无法使用桶。如果您想将其发布为答案而不是评论,我会接受它。
通常是循环依赖。
我也遇到过循环依赖的问题。值得注意的是,较新版本的 webpack 更能告诉你这一点
看起来像循环依赖,如果你使用 angular >=4 这样你就可以摆脱 intex.ts (桶)并直接导入你需要的所有东西。

G
Günter Zöchbauer

从直接声明它的文件而不是桶中导入它。

我不知道究竟是什么导致了这个问题,但我看到它多次提到(可能是某种循环依赖)。

它也应该可以通过改变桶中出口的顺序来解决(不知道细节,但也提到过)


这是正确的,例如,如果您将服务注入到另一个服务中,而第一个服务需要首先进入桶中。
由于存在很多此类问题,Angular2 团队不再推荐使用桶。很高兴听到我能帮忙:)
不知道 Angular 2 团队不推荐桶。如果是这样,他们应该在讨论他们的好处的 glossary 中注明。 angular2-webpack-starter 之类的项目不应使用它们。
它似乎已修复(在 2.0.2 中不是问题)。我发现桶仍然有用,特别是当我需要在不同模块之间导入多个模型和服务时。当它不起作用时,这个 import { cleanValues, getState, FirebaseService, NotificationService, ... } from '../../shared/services'; 很痛苦(; NgModule 对单例服务没有帮助......
Argghh 我通过更改桶(index.ts)文件中的导出顺序解决了这个问题。非常感谢
J
J.P.

除了之前给出的答案之外,当您的可注入服务缺少实际的 @Injectable() 装饰器时,似乎也会引发此错误。因此,在调试循环依赖项和导入/导出顺序之前,请先简单检查一下您的服务是否确实定义了 @Injectable()

这适用于当前最新的 Angular Angular 2.1.0。

I opened an issue on this matter


是的,这个错误通常是因为您忘记添加 @Injectable,例如,您可能只是从“@angular/router”导入 Router,而没有该可注入,这个错误总是会发生(只要您决定一行代码使用注入的路由器。
很棒的答案,我的问题是我在服务中添加了一个方法,并且没有在最后一个大括号后添加分号。我不知道为什么必须这样,但在组件类中并非如此......现在我很高兴继续前进!
我有一个简单的模型给了我这个错误。我使用了在模型的构造函数中创建属性的快捷方式。属性的类型只有 string 和 int。然后突然这个问题开始发生。添加 @Injectable() 解决了这个问题。很奇怪,因为我的其他模型都没有添加 Injectable。我必须补充一点,在添加这个新模型之前我升级了很多库。可能与它有关,但现在正在工作。谢谢。
@Moutono 正确。在您的服务中使用空构造函数时,似乎不会触发依赖注入并且不需要 @injectable()。这本身就是另一个奇怪之处。为了更好的衡量,我仍然会添加它,只是为了你什么时候应该决定注入一些东西。
请记住,如果您的服务有一个也需要用 @Injectable() 装饰的基类
Z
Zabavsky

从 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 Manual: ForwardRef

Forward references in Angular 2


forwardRef() 已经存在于 alpha 中;-) 只有在同一文件中进一步声明了 Mobile 服务时才需要它。如果类在不同的文件中,则不需要 forwardRef()
Günter Zöchbauer,我仍在尝试找出我的代码的真正问题,但与此同时 forwardRef() 确实有助于摆脱 Can't resolve all parameters for ... 消息。至少该组件正在工作,而我正在寻找更好的问题解决方案。 (是的,失败的依赖项是直接从其文件中导入的)
@GünterZöchbauer 我已经用参考更新了我的答案。我不是想从您的答案中删除,但这实际上解决了问题,人们需要了解它。如果您用谷歌搜索该问题,则没有使用 forwardRef 的结果。很难找到。昨天花了我一整天来解决这个问题。
诡异的。我发布了至少十几个建议自己使用 foreardRef 但在引入 NgModule 后不再使用的答案。我不担心失去代表。我只是好奇你为什么在几个月后不再出现这个问题后遇到这个问题。过几天我回家再仔细看看。非常感谢您的反馈。
如果有人也对导入感到迷茫: import { Component, Inject, ForwardRefFn, forwardRef } from '@angular/core';
K
KANJICODER

错误#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 { ... }

但这不会成为单身人士吗?如果我想要每个依赖项上的新实例怎么办?
C
Community

如前所述,该问题是由循环依赖引起的桶内的导出排序引起的。

更详细的解释在这里:https://stackoverflow.com/a/37907696/893630


订购并没有解决我的问题。不使用枪管。
S
Stephen Paul

我通过将服务 A 注入服务 B 也遇到了这种情况,反之亦然。

我认为这很快失败是一件好事,因为无论如何都应该避免它。如果您希望您的服务更加模块化和可重用,最好尽可能避免循环引用。此 post 突出了围绕它的陷阱。

因此,我有以下建议:

如果您觉得类交互过于频繁(我说的是功能嫉妒),您可能需要考虑将 2 个服务合并为 1 个类。

如果上述方法对您不起作用,请考虑使用第三个服务(一个 EventService),两个服务都可以注入该服务以交换消息。


这绝对是发生在我身上的事情,这就是要走的路。如果您知道自己有多个需要更新的服务,请使用 EventService。它更具可扩展性,因为当您基于这些事件扩展应用程序时,您无疑必须利用这些事件。
J
JsAndDotNet

为了搜索者的利益;我得到了这个错误。这只是一个缺少的@符号。

即这会产生 Can't resolve all parameters for MyHttpService 错误。

Injectable()
export class MyHttpService{
}

添加缺少的 @ 符号可以修复它。

@Injectable()
export class MyHttpService{
}

在我的例子中,我在@Injectable 和服务类定义之间添加了额外的类和接口,所以服务类不再被标记为可注入的。
如果您完全忘记了使用其他可注入服务的服务类上的 @Injectable() 装饰器,那么您装饰不当的服务也会引发此错误。
S
Stewart_R

另一种可能性是在 tsconfig.json 中没有将 emitDecoratorMetadata 设置为 true

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}

你能详细说明一下吗?
T
Tomasz

除了缺少的 @Injectable() 装饰器

抽象类中缺少 @Injectable() 装饰器导致无法解析服务的所有参数:(?) 装饰器需要存在于 MyService 以及派生类 BaseService

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

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

我就是这种情况。
A
AJ Richardson

就我而言,我需要将 import "core-js/es7/reflect"; 添加到我的应用程序以使 @Injectable 工作。


现在是 'core-js/features/reflect'。此外,仅在 JIT (dev) 模式下才需要 polyfill,因此可以使用 webpack 中的动态导入和“魔术注释”有条件地加载它。例如: if (process.env.NODE_ENV !== 'production') { import(/* webpackMode: "eager" */ 'core-js/features/reflect').then(() => {}) ;}。请参阅webpack.js.org/api/module-methods/#magic-comments
M
M K

如果您的服务 A 依赖于服务 B 的静态属性/方法,并且服务 B 本身通过依赖注入依赖于服务 A,则会出现此错误。所以它是一种循环依赖,尽管它不是因为属性/方法是静态的。可能是与 AOT 结合使用的错误。


当依赖于在同一个文件中简单定义的函数时,我也有它。将其拆分为单独的文件可以修复它。
谢谢你提到它。我发现自己处于确切的境地。我没有意识到直接访问静态类可能与 DI 有关。我有这个方案:A -> B 并且他们都使用相同的静态类。 forwardRef 的解决方案会有所帮助,但我将看看如何解决这个问题。我可能会尝试从这个静态类中创建一个真正的服务(这也会带来更好的设计)。
A
Alf Moh

就我而言,这是因为我没有声明构造函数参数的类型。

我有这样的事情:

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

然后将其更改为下面的代码解决了我的问题。

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

o
otiai10

This answer 可能对这个问题很有帮助。此外,就我而言,将服务导出为 default 是原因。

错误的:

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

正确的:

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

r
repo

对我来说,@Injectable 中缺少 ()。正确的是@Injectable()


或者在我的情况下不小心删除了@
M
Matjaz Hirsman

从可注入构造函数()方法中删除参数解决了我的情况。


这也正是我的问题。我是来发的,但发现你先发了! +1
那么如何将参数发送到可重用服务?
T
Tinh Dang

就我而言,这是因为插件 Augury,禁用它会正常工作。替代选项是aot,也可以。

所有功劳归于@Boboss74,他在这里发布了答案:https://github.com/angular/angular/issues/23958


O
Ophir Stern

对我来说,这个问题更烦人,我在一个服务中使用一个服务,却忘记将它作为依赖项添加到 appModule 中!希望这可以帮助某人节省几个小时分解应用程序只是为了重新构建它


我只是缺少一个 @Inject 注释。我忽略了错误消息所说的内容。如果您不怀疑循环依赖,只需转到错误中提到的类并查看所有构造函数参数和任何带有 @Inject 注释的类成员,并确保您对所有这些都进行了正确的 DI。更多关于 DI 的信息:angular.io/docs/ts/latest/guide/dependency-injection.html
s
sarora

由于错误中缺乏反馈,这可能是一个非常难以调试的问题。如果您担心实际的循环依赖,这里是堆栈跟踪中最重要的内容 a) 服务的名称 b) 该服务中带有问号的构造函数参数,例如,如果它看起来像这样:

无法解析 AuthService 的所有参数:([object Object], [object Object], [object Object], [object Object], ?)

那么这意味着第 5 个参数是一个也依赖于 AuthService 的服务。即问号,表示它没有被 DI 解决。

从那里,您只需要通过重构代码来解耦这 2 个服务。


L
Leepians

添加 Injectable 解决了我的问题:

错误代码

import { Observable } from 'rxjs';
import { io } from 'socket.io-client';
import { HttpClient } from '@angular/common/http';

export class Chat {

修复后

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { io } from 'socket.io-client';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class Chat {

m
maleman

我通过输入错误的服务名称遇到此错误,即构造函数(私有 myService:MyService)。

对于拼写错误的服务,我可以通过检查 Chrome->Console 中的页面来确定哪个服务是问题(我在构造函数中列出了几个)。您将通过显示对象对象、对象对象、? (或类似的东西)。注意“?”在哪里是,这就是导致问题的服务的位置。


S
Shivang Gupta

您必须在 @Component 装饰器或声明组件的模块中添加提供者数组。在组件内部,您可以执行以下操作:

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

S
Satendra

在我的例子中,将错误的参数传递给构造函数会产生这个错误,关于这个错误的基本想法是你在不知不觉中将一些错误的参数传递给了任何函数。

export class ProductComponent {
    productList: Array<Product>;

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

我通过删除那个论点解决了这个问题。


A
Ahmed Elkoussy

对我来说,当我在 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';

M
Muhammed Ozdogan

就我而言,我试图扩展“NativeDateAdapter”以覆盖“format(date: Date, displayFormat: Object)”方法。

在 AngularMaterial-2 DatePicker 中。

所以基本上我忘了添加 @Injectable 注释。

在我将它添加到我的“CustomDateAdapter”类之后:

@Injectable({
  providedIn: 'root'
})

错误消失了。


这对我有用,但我不知道为什么。是否需要同时提供服务和通过 DI 接收它的组件在:root 中才能使 DI 工作?
C
Cristian Traìna

明白了!

如果上述答案都没有帮助您,那么您可能正在从组件注入服务的同一个文件中导入一些元素。

我解释得更好:

这是服务文件:

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

因此,即使符号不在同一个组件内,而只是在同一个文件内,它也会导致问题。将符号(它可以是函数、常量、类等等)移到别处,错误就会消失


l
lolcatzftw

对于 Angular 6 和更新版本,请尝试

@Injectable({
  providedIn: 'root'
})

..就在您的服务等级之上,中间没有其他线条

优点

无需将服务添加到任何模块(将“自动发现”)

服务将是一个单例(因为它将被注入到根中)

[angular docs]


C
Community

尽管可能已经提到了从桶中导出类的顺序,但以下场景也可能产生相同的效果。

假设您有从 A 依赖于 BC 的同一文件中导出的类 ABC

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

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

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

由于 Angular 尚不知道 依赖 类(即在本例中为类 BC),(可能在运行时 Angular 对类 {3 的依赖注入过程中) }) 引发错误。

解决方案

解决方案是在 DI 完成的类之前声明和导出依赖类。

即在上述情况下,类 A 在其依赖项定义后立即声明:

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

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

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

M
Menelaos Kotsollaris

在我的例子中,我从同一个组件文件中导出了一个类和一个枚举:

mComponent.component.ts

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

然后,我尝试使用 MyComponentClass 的子级的 MyEnum。这导致无法解析所有参数错误

通过将 MyEnumMyComponentClass 移到单独的文件夹中,解决了我的问题!

正如 Günter Zöchbauer 所说,这是因为服务或组件是循环依赖的。


S
Simon_Weaver

如果您的服务与组件(使用它)在同一个文件中定义,并且服务是在文件中的组件之后定义的,您可能会收到此错误。这是由于其他人提到的相同的“forwardRef”问题。目前 VSCode 不能很好地向您显示此错误并且构建成功编译。

由于编译器的工作方式(可能与摇树相关),使用 --aot 运行构建可以掩盖此问题。

解决方案:确保服务定义在另一个文件中或在组件定义之前。 (我不确定在这种情况下是否可以使用 forwardRef,但这样做似乎很笨拙)。

如果我有一个非常简单的服务,它与一个组件(有点像视图模型)紧密相关 - 例如。 ImageCarouselComponent,我可以将其命名为 ImageCarouselComponent.service.ts,以免它与我的其他服务混淆。


l
lucbonnin

就我而言,这是一个循环引用。我让 MyService 调用 Myservice2 和 MyService2 调用 MyService。

不好 :(


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅