Я создал базовое приложение на 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: (?).
У меня есть сервис в функции начальной загрузки, поэтому у него есть провайдер. И я, кажется, могу вставить его в конструктор любого из моих других компонентов без проблем.
Импортируйте его из файла, где он объявлен непосредственно, а не в бочке.
Я не знаю, что именно вызывает проблему, но я видел, как это упоминалось несколько раз (вероятно, какая-то циклическая зависимость).
Он также должен быть исправлен путем изменения порядка экспорта в стволе (не знаю деталей, но также упоминался)
В дополнение к предыдущим приведенным ответам, похоже, эта ошибка также возникает, когда вашей инъекционной службе не хватает фактического декоратора @Injectable()
. Поэтому перед тем, как вы отлаживаете элемент циклической зависимости и порядок импорта/экспорта, выполните простую проверку, действительно ли ваша служба имеет @Injectable()
.
Это относится к текущему Angular последнему, Angular 2.1.0.
Начиная с 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))
к параметру конструктора в исходном исходном коде вопроса устранит проблему.
forwardRef()
уже был в альфа- forwardRef()
;-) Это необходимо только в том случае, если Mobile
служба объявлена ниже в том же файле. Если классы находятся в разных файлах, нет необходимости в forwardRef()
forwardRef()
помог избавиться от сообщения Can't resolve all parameters for ...
удается Can't resolve all parameters for ...
сообщения. По крайней мере, компонент работает, пока я ищу лучшее решение проблемы. (И да, ошибочная зависимость импортируется непосредственно из ее файла)
НЕПРАВИЛЬНО # 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 { ... }
Как уже было сказано, проблема вызвана экспортным упорядочением внутри ствола, вызванным круговыми зависимостями.
Более подробное объяснение здесь: https://stackoverflow.com/questions/37902476/automatic-ordering-of-exports-in-index-ts-makes-app-crash
Я также столкнулся с этим, вводя службу A в службу B и наоборот.
Я думаю, что это хорошо, что это быстро проваливается, так как, вероятно, его все равно следует избегать. Если вы хотите, чтобы ваши услуги были более модульными/многоразовыми, лучше избегать циклических ссылок в максимально возможной степени. Этот пост освещает подводные камни, окружающие это.
Поэтому у меня есть следующие рекомендации:
EventService
), которую обе службы могут внедрить для обмена сообщениями.В интересах поисковиков; Я получил эту ошибку. Это был просто отсутствующий символ @.
т.е. Это вызывает ошибку Can't resolve all parameters for MyHttpService
.
Injectable()
export class MyHttpService{
}
Добавление отсутствующего символа @
исправляет его.
@Injectable()
export class MyHttpService{
}
В моем случае мне нужно было добавить import "core-js/es7/reflect";
в мое приложение, чтобы заставить @Injectable
работать.
Вы получаете эту ошибку, если у вас есть служба A, которая зависит от статического свойства/метода службы B и службы B зависит от сервиса A. Так что это своего рода циклическая зависимость, хотя это не так, поскольку свойство/метод статично. Вероятно, ошибка, возникающая в сочетании с AOT.
A -> B
и они оба использовали один и тот же статический класс. Решение с forwardRef
помогает, но я собираюсь посмотреть, как это можно распутать. Я, вероятно, постараюсь сделать реальный сервис из этого статического класса (это также приведет к лучшему дизайну).
В дополнение к отсутствующему декоратору @Injectable()
Отсутствует декодер @Injectable()
в абстрактном классе, который не может разрешить все параметры для службы: (?)
Декоратор должен присутствовать в MyService
, а также в производном классе BaseService
//abstract class
@Injectable()
abstract class BaseService { ... }
//MyService
@Injectable()
export class MyService extends BaseService {
.....
}
В моем случае это произошло потому, что я не объявлял тип для параметра конструктора.
У меня было что-то вроде этого:
constructor(private URL, private http: Http) { }
а затем, изменив его на приведенный ниже код, решила мою проблему.
constructor(private URL : string, private http: Http) {}
для меня это было просто отсутствие ()
в @Injectable. Proper - это @Injectable()
Удаление параметров из метода инъецируемого конструктора() разрешило его для моего случая.
В моем случае это было из-за плагина Augury, отключить его будет нормально. Альтернативный вариант есть, тоже работает.
все кредиты @Boboss74, он разместил ответ здесь: https://github.com/angular/angular/issues/23958
Для меня, я получил эту ошибку, когда я по ошибке отключил этот импорт в файле 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';
Другая возможность - не устанавливать для emitDecoratorMetadata
значение true в tsconfig.json.
{
"compilerOptions": {
...
"emitDecoratorMetadata": true,
...
}
}
В моем случае, передача неправильных параметров в конструктор генерирует эту ошибку, основная идея этой ошибки заключается в том, что вы неосознанно передали некоторые неправильные аргументы любой функции.
export class ProductComponent {
productList: Array<Product>;
constructor(productList:Product) {
// productList:Product this arg was causing error of unresolved parameters.
this.productList = [];
}
}
Я решил это, просто убрав этот аргумент.
Вам нужно добавить массив поставщиков в @Component decorator или в модуль, в котором объявлен ваш компонент. Внутренний компонент можно сделать следующим образом:
@Component({
moduleId: module.id,
selector: 'pm-header',
templateUrl: 'header.component.html',
styleUrls: ['header.component.css'],
directives: [ROUTER_DIRECTIVES, NgClass],
providers: [MobileService]
})
Ну, для меня проблема была еще более раздражающей, я использовал сервис в сервисе и забыл добавить его как зависимость в appModule! Надеюсь, что это поможет кому-то сэкономить несколько часов, нарушающих приложение, только чтобы восстановить его снова.
@Inject
аннотации @Inject
. Я упускал из виду именно то, что говорится в сообщении об ошибке. Если вы не подозреваете о циклических зависимостях, просто перейдите к классу, указанному в ошибке, и посмотрите на все параметры конструктора и все члены класса, аннотированные @Inject
и убедитесь, что вы делаете DI правильно для всех них. Подробнее о DI здесь: angular.io/docs/ts/latest/guide/dependency-injection.html
В моем случае причина была следующая:
Как следствие, при попытке создать объект A конструктор по умолчанию потерпел неудачу. Я понятия не имею, почему это не было ошибкой компиляции.
Я исправил это, просто добавив конструктор в A, который правильно назвал конструктор B.
В моем случае я пытался расширить NativeDateAdapter
" NativeDateAdapter
", чтобы переопределить метод format(date: Date, displayFormat: Object)
".
В AngularMaterial-2 DatePicker.
Поэтому я забыл добавить @Injectable
.
После того, как я добавлю это в мой класс "CustomDateAdapter":
@Injectable({
providedIn: 'root'
})
Ошибка ушла.
Хотя, возможно, упоминалось упорядочение экспортируемых классов из бочек, следующий сценарий также может дать тот же эффект.
Предположим, у вас есть классы 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) {}
}
Я столкнулся с этой ошибкой, ошибочно указав имя службы, т.е. конструктор (private myService: MyService).
Для служб с ошибками я смог определить, какая из этих служб является проблемой (у меня было несколько перечисленных в конструкторе), просмотрев страницу в Chrome- > Console. Вы увидите как часть сообщения список параметров "parameter", показывая объект Object, Object Object,? (или что-то типа того). Обратите внимание, где "?" это и есть позиция службы, которая вызывает проблему.
В моем случае это была круговая ссылка. У меня был MyService, вызывающий Myservice2, и MyService2, вызывающий MyService.
Нехорошо :(
Если ваша служба определена в том же файле, что и компонент (который ее использует), а служба определена после компонента в файле, вы можете получить эту ошибку. Это связано с той же проблемой 'forwardRef', о которой упоминали другие. В настоящее время VSCode не очень хорошо показывает эту ошибку, и сборка успешно компилируется.
Запуск сборки с --aot
может замаскировать эту проблему из-за того, как работает компилятор (вероятно, связанный с дрожанием дерева).
Решение. Убедитесь, что служба определена в другом файле или перед определением компонента. (Я не уверен, можно ли использовать forwardRef в этом случае, но это кажется неуклюжим).
Если у меня есть очень простой сервис, который очень сильно привязан к компоненту (вроде как модель представления) - например. ImageCarouselComponent
, я могу назвать его ImageCarouselComponent.service.ts
чтобы он не смешивался с другими моими службами.
В моем случае я взял зависимость от службы, которая не имела зависимостей, и поэтому я не добавил функцию constructor()
в класс службы. Я добавил конструктор без параметров в зависимый класс обслуживания, и все начало работать.
В моем случае я экспортировал Class и Enum из одного и того же файла компонента:
mComponent.component.ts
:
export class MyComponentClass{...}
export enum MyEnum{...}
Затем я пытался использовать MyEnum
от потомка MyComponentClass
. Это было причиной ошибки "Не удается разрешить все параметры".
Переместив MyEnum
в отдельную папку из MyComponentClass
, это решило мою проблему!
Как отметил Гюнтер Цохбауэр, это происходит из-за того, что услуга или компонент циклически зависимы.
Для меня это было потому, что у меня была пустая строка между моим декоратором @Component
и моим классом Component. Это заставило декоратора не применяться к классу.
Для меня это было потому, что я перестал использовать флаг -aot, пытаясь ускорить время компиляции.
ng serve -aot
Иногда это происходит, когда вы объявили Angular встроенный модуль (HttpClientModule, HttpErrorResponse и т.д.) в app.module.js. Я также столкнулся с той же проблемой, но теперь решил.
Ошибка, которую я сделал, это указать HttpClientModule в Провайдеры вместо Импорт Angular Module
Это происходит при обращении к interface
.
Изменение interface
для class
исправлено, работа с и без @Inject
.
При использовании импорта стволов - сначала сначала импортируйте инъекции, как правило.
'../'
index.ts
(Barrel)? Можете ли вы попробовать импортировать его из файла, в котором он объявлен напрямую?