Ошибка углового цифрового входа - ИСКЛЮЧЕНИЕ: не удается разрешить все параметры

301

Я создал базовое приложение на 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: (?).

У меня есть сервис в функции начальной загрузки, поэтому у него есть провайдер. И я, кажется, могу вставить его в конструктор любого из моих других компонентов без проблем.

  • 12
    Может быть импорт? Является ли '../' index.ts (Barrel)? Можете ли вы попробовать импортировать его из файла, в котором он объявлен напрямую?
  • 0
    Чудесным образом это, кажется, исправило это! Странно, что это не сработает, если использовать другие компоненты, с которыми я тестировал сервис. Если вы хотите опубликовать это как ответ вместо комментария, я приму это.
Показать ещё 3 комментария
Теги:
angular

32 ответа

352
Лучший ответ

Импортируйте его из файла, где он объявлен непосредственно, а не в бочке.

Я не знаю, что именно вызывает проблему, но я видел, как это упоминалось несколько раз (вероятно, какая-то циклическая зависимость).

Он также должен быть исправлен путем изменения порядка экспорта в стволе (не знаю деталей, но также упоминался)

  • 14
    это правильно, если у вас есть, например, сервис, внедренный в другой сервис, который должен быть первым в бочке.
  • 14
    Команда Angular2 больше не рекомендует бочки из-за множества таких проблем. Рад слышать, что смог помочь :)
Показать ещё 11 комментариев
261

В дополнение к предыдущим приведенным ответам, похоже, эта ошибка также возникает, когда вашей инъекционной службе не хватает фактического декоратора @Injectable(). Поэтому перед тем, как вы отлаживаете элемент циклической зависимости и порядок импорта/экспорта, выполните простую проверку, действительно ли ваша служба имеет @Injectable().

Это относится к текущему Angular последнему, Angular 2.1.0.

Я открыл проблему по этому вопросу.

  • 20
    или, может быть, забытый символ @ !!!
  • 2
    @osdamv Ух ты, действительно. Хорошо подмечено.
Показать ещё 8 комментариев
92

Начиная с 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

  • 3
    forwardRef() уже был в альфа- forwardRef() ;-) Это необходимо только в том случае, если Mobile служба объявлена ниже в том же файле. Если классы находятся в разных файлах, нет необходимости в forwardRef()
  • 4
    Гюнтер Цохбауэр, я все еще пытаюсь выяснить реальную проблему с моим кодом, но тем временем forwardRef() помог избавиться от сообщения Can't resolve all parameters for ... удается Can't resolve all parameters for ... сообщения. По крайней мере, компонент работает, пока я ищу лучшее решение проблемы. (И да, ошибочная зависимость импортируется непосредственно из ее файла)
Показать ещё 10 комментариев
46

НЕПРАВИЛЬНО # 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} из '@angular/core';

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

ПРАВИЛЬНО:

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

Как уже было сказано, проблема вызвана экспортным упорядочением внутри ствола, вызванным круговыми зависимостями.

Более подробное объяснение здесь: https://stackoverflow.com/questions/37902476/automatic-ordering-of-exports-in-index-ts-makes-app-crash

  • 1
    Заказ не решил мою проблему. Не используя ствол сделал.
17

Я также столкнулся с этим, вводя службу A в службу B и наоборот.

Я думаю, что это хорошо, что это быстро проваливается, так как, вероятно, его все равно следует избегать. Если вы хотите, чтобы ваши услуги были более модульными/многоразовыми, лучше избегать циклических ссылок в максимально возможной степени. Этот пост освещает подводные камни, окружающие это.

Поэтому у меня есть следующие рекомендации:

  • Если вы чувствуете, что классы взаимодействуют слишком часто (я говорю о зависти к функциям), вы можете рассмотреть возможность объединения двух сервисов в один класс.
  • Если вышеперечисленное не работает для вас, рассмотрите возможность использования третьей службы (EventService), которую обе службы могут внедрить для обмена сообщениями.
  • 1
    Это определенно то, что случилось со мной, и это путь. Если вы знаете, что у вас есть несколько служб, требующих обновления, используйте EventService. Он более расширяемый, поскольку вам, без сомнения, придется задействовать эти события при расширении приложения на основе этих событий.
  • 0
    Спасибо, это ответ, который решил мой!
16

В интересах поисковиков; Я получил эту ошибку. Это был просто отсутствующий символ @.

т.е. Это вызывает ошибку Can't resolve all parameters for MyHttpService.

Injectable()
export class MyHttpService{
}

Добавление отсутствующего символа @ исправляет его.

@Injectable()
export class MyHttpService{
}
  • 2
    В моем случае я добавил дополнительные классы и интерфейсы между @Injectable и определением класса сервиса, поэтому класс сервиса больше не помечался как инъекционный.
  • 0
    Если вы полностью забудете декоратор @Injectable () для класса обслуживания, который использует другие сервисы для инъекций, то ваш неправильно оформленный сервис также выдаст эту ошибку.
8

В моем случае мне нужно было добавить import "core-js/es7/reflect"; в мое приложение, чтобы заставить @Injectable работать.

8

Вы получаете эту ошибку, если у вас есть служба A, которая зависит от статического свойства/метода службы B и службы B зависит от сервиса A. Так что это своего рода циклическая зависимость, хотя это не так, поскольку свойство/метод статично. Вероятно, ошибка, возникающая в сочетании с AOT.

  • 0
    У меня также было это, когда есть зависимость от функции, просто определенной в том же файле. Разделение на отдельные файлы исправило это.
  • 1
    Спасибо, что упомянули это. Я оказался в точной ситуации. Я не осознавал, что прямой доступ к статическим классам может иметь какое-то отношение к DI. У меня была такая схема: A -> B и они оба использовали один и тот же статический класс. Решение с forwardRef помогает, но я собираюсь посмотреть, как это можно распутать. Я, вероятно, постараюсь сделать реальный сервис из этого статического класса (это также приведет к лучшему дизайну).
7

В дополнение к отсутствующему декоратору @Injectable()

Отсутствует декодер @Injectable() в абстрактном классе, который не может разрешить все параметры для службы: (?) Декоратор должен присутствовать в MyService, а также в производном классе BaseService

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

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

В моем случае это произошло потому, что я не объявлял тип для параметра конструктора.

У меня было что-то вроде этого:

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

а затем, изменив его на приведенный ниже код, решила мою проблему.

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

для меня это было просто отсутствие () в @Injectable. Proper - это @Injectable()

  • 0
    Или в моем случае случайно удалить @
5

Удаление параметров из метода инъецируемого конструктора() разрешило его для моего случая.

  • 0
    Это тоже была моя проблема. Я пришел, чтобы опубликовать это, но обнаружил, что вы сделали первым! +1
4

В моем случае это было из-за плагина Augury, отключить его будет нормально. Альтернативный вариант есть, тоже работает.

все кредиты @Boboss74, он разместил ответ здесь: https://github.com/angular/angular/issues/23958

  • 0
    благодаря @ Boboss74, он разместил ответ здесь: github.com/angular/angular/issues/23958 . Просто подумал, что многие люди найдут здесь результаты поиска, так что это может помочь поделиться этим здесь.
  • 0
    Вначале я не поверил, что это может быть проблемой, но на самом деле плагин Augury вызвал ошибку - после его отключения приложение начинает работать так, как оно предполагает работу.
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

Другая возможность - не устанавливать для emitDecoratorMetadata значение true в tsconfig.json.

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}
2

В моем случае, передача неправильных параметров в конструктор генерирует эту ошибку, основная идея этой ошибки заключается в том, что вы неосознанно передали некоторые неправильные аргументы любой функции.

export class ProductComponent {
    productList: Array<Product>;

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

Я решил это, просто убрав этот аргумент.

2

Вам нужно добавить массив поставщиков в @Component decorator или в модуль, в котором объявлен ваш компонент. Внутренний компонент можно сделать следующим образом:

@Component({
  moduleId: module.id,
  selector: 'pm-header',
  templateUrl: 'header.component.html',
  styleUrls: ['header.component.css'],
  directives: [ROUTER_DIRECTIVES, NgClass],
  providers: [MobileService]
})
  • 0
    Это было причиной моей проблемы
2

Ну, для меня проблема была еще более раздражающей, я использовал сервис в сервисе и забыл добавить его как зависимость в appModule! Надеюсь, что это поможет кому-то сэкономить несколько часов, нарушающих приложение, только чтобы восстановить его снова.

  • 1
    Мне просто не @Inject аннотации @Inject . Я упускал из виду именно то, что говорится в сообщении об ошибке. Если вы не подозреваете о циклических зависимостях, просто перейдите к классу, указанному в ошибке, и посмотрите на все параметры конструктора и все члены класса, аннотированные @Inject и убедитесь, что вы делаете DI правильно для всех них. Подробнее о DI здесь: angular.io/docs/ts/latest/guide/dependency-injection.html
1

В моем случае причина была следующая:

  • мой инъекционный сервис А продлил еще один класс Б
  • У B был конструктор, который требовал аргумента
  • Я не определил ни одного конструктора в A

Как следствие, при попытке создать объект A конструктор по умолчанию потерпел неудачу. Я понятия не имею, почему это не было ошибкой компиляции.

Я исправил это, просто добавив конструктор в A, который правильно назвал конструктор B.

1

В моем случае я пытался расширить NativeDateAdapter " NativeDateAdapter ", чтобы переопределить метод format(date: Date, displayFormat: Object) ".

В AngularMaterial-2 DatePicker.

Поэтому я забыл добавить @Injectable.

После того, как я добавлю это в мой класс "CustomDateAdapter":

@Injectable({
  providedIn: 'root'
})

Ошибка ушла.

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) еще не известны Angular, (вероятно, во время выполнения во время процесса внедрения зависимостей Angular в класс 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

Я столкнулся с этой ошибкой, ошибочно указав имя службы, т.е. конструктор (private myService: MyService).

Для служб с ошибками я смог определить, какая из этих служб является проблемой (у меня было несколько перечисленных в конструкторе), просмотрев страницу в Chrome- > Console. Вы увидите как часть сообщения список параметров "parameter", показывая объект Object, Object Object,? (или что-то типа того). Обратите внимание, где "?" это и есть позиция службы, которая вызывает проблему.

0

В моем случае это была круговая ссылка. У меня был MyService, вызывающий Myservice2, и MyService2, вызывающий MyService.

Нехорошо :(

0

Если ваша служба определена в том же файле, что и компонент (который ее использует), а служба определена после компонента в файле, вы можете получить эту ошибку. Это связано с той же проблемой 'forwardRef', о которой упоминали другие. В настоящее время VSCode не очень хорошо показывает эту ошибку, и сборка успешно компилируется.

Запуск сборки с --aot может замаскировать эту проблему из-за того, как работает компилятор (вероятно, связанный с дрожанием дерева).

Решение. Убедитесь, что служба определена в другом файле или перед определением компонента. (Я не уверен, можно ли использовать forwardRef в этом случае, но это кажется неуклюжим).

Если у меня есть очень простой сервис, который очень сильно привязан к компоненту (вроде как модель представления) - например. ImageCarouselComponent, я могу назвать его ImageCarouselComponent.service.ts чтобы он не смешивался с другими моими службами.

0

В моем случае я взял зависимость от службы, которая не имела зависимостей, и поэтому я не добавил функцию constructor() в класс службы. Я добавил конструктор без параметров в зависимый класс обслуживания, и все начало работать.

0

В моем случае я экспортировал Class и Enum из одного и того же файла компонента:

mComponent.component.ts:

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

Затем я пытался использовать MyEnum от потомка MyComponentClass. Это было причиной ошибки "Не удается разрешить все параметры".

Переместив MyEnum в отдельную папку из MyComponentClass, это решило мою проблему!

Как отметил Гюнтер Цохбауэр, это происходит из-за того, что услуга или компонент циклически зависимы.

0

Для меня это было потому, что у меня была пустая строка между моим декоратором @Component и моим классом Component. Это заставило декоратора не применяться к классу.

0

Для меня это было потому, что я перестал использовать флаг -aot, пытаясь ускорить время компиляции.

 ng serve -aot
  • 0
    Это решило мою проблему с эффектами ngrx.
0

Иногда это происходит, когда вы объявили Angular встроенный модуль (HttpClientModule, HttpErrorResponse и т.д.) в app.module.js. Я также столкнулся с той же проблемой, но теперь решил.

Ошибка, которую я сделал, это указать HttpClientModule в Провайдеры вместо Импорт Angular Module

0

Это происходит при обращении к interface.

Изменение interface для class исправлено, работа с и без @Inject.

0

При использовании импорта стволов - сначала сначала импортируйте инъекции, как правило.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню