ВИХІД: Не вдається вирішити всі параметри


431

Я створив базовий додаток у Angular 2, але у мене виникли дивні проблеми, коли я не можу ввести службу в один із своїх компонентів. Однак він добре вводить будь-який із трьох створених мною компонентів.

Для початку це послуга:

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: (?).

У мене є служба у функції завантаження, щоб вона мала провайдера. І я, здається, зможу без проблем ввести його в конструктор будь-якого іншого мого компонента.


14
Можливо, імпорт? Є чи (Barrel)? Чи можете ви спробувати імпортувати його з файла, де він оголошений безпосередньо замість цього? '../'index.ts
Günter Zöchbauer

Чудо, здається, це виправили! Як не дивно, що це не працюватиме за допомогою бочки, коли інші компоненти, з якими я тестував сервіс, робили. Якщо ви хочете опублікувати це як відповідь замість коментаря, я прийму це.
Кіт Отто

11
Взагалі кругова залежність.
Гері

У мене виникло це питання і з круговою залежністю. Варто зазначити, що новіші версії веб-пакету набагато краще розповідають про це
Enn

Виглядає як кругова залежність. Якщо ви використовуєте angular> = 4, ви можете позбутися від intex.ts (бочка) та імпортувати все необхідне безпосередньо.
Rammgarot

Відповіді:


457

Імпортуйте його з файлу, де оголошено безпосередньо замість бочки.

Я не знаю, що саме викликає проблему, але я бачив, як це згадувалося кілька разів (можливо, якась кругова залежність).

Це також має бути зафіксовано, змінивши порядок експорту в барелі (не знаю деталей, але згадувалося також)


16
це правильно, якщо у вас є, наприклад, служба, введена в іншу службу, для початку якої потрібно зайти першою в бочку.
Жоао Гарін

17
Команда Angular2 більше не рекомендує бочки через багато таких проблем. Радий почути, що можу допомогти :)
Günter Zöchbauer

13
Не знав, що команда Angular 2 не рекомендує бочки. Якщо це так, вони повинні зазначити, що у словнику, який обговорює їхню користь. І такі проекти, як angular2-webpack-starter, не повинні їх використовувати.
Блакитний

3
Все це було виправлено (не проблема в 2.0.2). Я вважаю бочки все ще корисними, особливо коли мені потрібно імпортувати кілька моделей та послуг між різними модулями. Це import { cleanValues, getState, FirebaseService, NotificationService, ... } from '../../shared/services';було болем, коли це не спрацювало (; NgModuleдопомога не в одиночних послугах ...
Сакса

3
Argghh Я вирішив це, змінивши порядок експорту у файл бареля (index.ts) .. велике спасибі
Спок

331

На додаток до попередніх відповідей, схоже, ця помилка викидається і тоді, коли у вашій службі ін’єкцій відсутній власний @Injectable()декоратор. Тому перед тим, як налагодити річ циклічної залежності та порядок імпорту / експорту, проведіть просту перевірку, чи справді @Injectable()визначена ваша послуга .

Це стосується поточної версії Angular 2.1.0, Angular 2.1.0.

Я відкрив питання з цього приводу .


Так, ця помилка, як правило, тому, що ви забули додати @Injectable, і, наприклад, ви можете просто імпортувати Routerз "@ angular / router", і без цього ін'єкційного варіанту ця помилка буде завжди (як тільки ви вирішите зробити один рядок використання коду, який вводив роутер.
Ерік Бішард

Дивовижна відповідь, моє питання полягало в тому, що я додав метод в моїй службі і не додав напівкрапки після остаточного дужки. Я поняття не маю, чому так має бути, але в класах компонентів це не так ... поки що я тільки радий рухатися далі!
egimaben

У мене була проста модель, яка дала мені цю помилку. Я використав ярлик, де ви створюєте свої властивості в конструкторі моделі. Типи властивостей були лише string та int. Потім раптом ця проблема почала виникати. Додавання @Injectable () вирішило проблему. Дивно, тому що жодна з інших моїх моделей не додала ін'єкцій. Треба додати, що я оновив досить багато бібліотек, перш ніж додати цю нову модель. Можливо, було з цим щось робити, але зараз працюю. Дякую.
Мутоно

@Moutono Правильно. З порожнім конструктором у вашій службі, введення залежності, схоже, не спрацьовує і @injectable()не потрібно. Що ще одна дивацтво на собі. На жаль, я все одно додав би це, просто для того, коли ви коли-небудь вирішите щось зробити.
JP ten Berge

Майте на увазі, що якщо у вашій службі є базовий клас, який теж повинен бути прикрашений @Injectable ()
Сем Шилес

110

Станом на Angular 2.2.3тепер існує forwardRef()утиліта, яка дозволяє вводити постачальників, які ще не визначені.

Не визначено, я маю на увазі, що карта введення залежності не знає ідентифікатора. Це те, що відбувається під час кругових залежностей. Ви можете мати кругові залежності в кутових, які дуже важко розплутати і побачити.

export class HeaderComponent {
  mobileNav: boolean = false;

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

}

Додавання @Inject(forwardRef(() => MobileService))параметра конструктора до вихідного коду питання вирішить проблему.

Список літератури

Кутовий посібник 2: ForwardRef

Переадресація посилань у Angular 2


3
forwardRef()був там уже в альфа ;-) Це потрібно лише в тому випадку, якщо Mobileсервіс оголошено далі в тому ж файлі. Якщо заняття в різних файлах, немає необхідностіforwardRef()
Günter Zöchbauer

4
Гюнтер Зехбауер, я все ще намагаюся з'ясувати справжню проблему свого коду, але тим часом forwardRef()допоміг позбутися Can't resolve all parameters for ...повідомлення. Принаймні, компонент працює, поки я шукаю кращого вирішення проблеми. (І так, невдала залежність імпортується безпосередньо зі свого файлу)
Nik

4
@ GünterZöchbauer Я оновив свою відповідь посиланнями. Я не намагаюся відібратись від вашої відповіді, але це насправді вирішує проблему, і люди повинні знати про неї. Якщо ви ставите Google запитання, немає результатів, які б сказали використовувати forwardRef. Це дуже важко знайти. Вчора вчора мене брали, щоб вирішити цю проблему.
Реакційний

Дивно. Я розмістив щонайменше десяток відповідей, які пропонують використовувати foreardRefсебе, але вже не після того, як NgModuleбув представлений. Мене не турбує втрата повторів. Мені просто цікаво, чому ти стикаєшся з цим після того, як це вже не вискочило з кількох місяців. Я ближче познайомлюсь, коли я повернуся додому через кілька днів. Дякую за відгуки.
Günter Zöchbauer

2
Якщо хтось також загубився з приводу імпорту: import {Component, Inject, ForwardRefFn, forwardRef} з "@ angular / core";
Натанаїл

69

WRONG # 1: Забуття декоратора:

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

WRONG # 2: Опущення символу "@":

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

WRONG # 3: Пропуск символів "()":

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

WRONG # 4: Малі літери "i":

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

WRONG # 5: Ви забули: import {Injectable} з '@ angular / core';

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

ПРАВИЛЬНО:

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

27

Як уже було сказано, проблема викликана замовленнями на експорт у барелі, що викликано круговими залежностями.

Більш детальне пояснення тут: https://stackoverflow.com/a/37907696/893630


3
Замовлення не вирішило моєї проблеми. Не використовуючи бочку зробив.
Michael Laffargue

21

Я також зіткнувся з цим, ввівши службу А в службу В і навпаки.

Я думаю, що це добре, що це не вдається швидко, тому що, мабуть, цього слід уникати . Якщо ви хочете, щоб ваші послуги були більш модульними та повторно використовувались, краще максимально уникати кругових посилань. Цей пост висвітлює підводні камені, що оточують це.

Тому в мене є такі рекомендації:

  • Якщо ви вважаєте, що заняття взаємодіють занадто часто (я кажу про заздрість до функції ), ви можете розглянути питання про об'єднання двох служб у 1 клас .
  • Якщо вищезгадане не працює для вас, подумайте про використання третьої послуги , (an EventService), яку обидві служби можуть вводити для обміну повідомленнями.

1
Це, безумовно, сталося зі мною, і це шлях. Якщо ви знаєте, що у вас є кілька служб, які потребують оновлень, використовуйте EventService. Це більш розширюється, оскільки, без сумніву, вам доведеться скористатися тими подіями, розширюючи програму на основі цих подій.
themightybun

17

На благо шукачів; Я отримав цю помилку. Це був просто зниклий символ @.

Тобто це створює Can't resolve all parameters for MyHttpServiceпомилку.

Injectable()
export class MyHttpService{
}

Додавання відсутнього @символу виправляє його.

@Injectable()
export class MyHttpService{
}

2
У моєму випадку я додав додаткові класи та інтерфейси між @Injectable та визначенням класу служби, тому клас обслуговування більше не позначався як ін'єкційний.
Герк

Якщо ви повністю забудете декоратор @Injectable () для класу обслуговування, який споживає інші послуги для ін'єкцій, то ваш неправильно оформлений сервіс також призведе до цієї помилки.
І. Бучан

10

У моєму випадку мені потрібно було додати import "core-js/es7/reflect";свою заявку, щоб зробити @Injectableроботу.


9

Інша можливість - не emitDecoratorMetadataвстановити значення true у tsconfig.json

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}

8

Ви отримуєте цю помилку, якщо у вас є служба A, яка залежить від статичної властивості / способу обслуговування B, а сама служба B залежить від послуги A через введення залежності. Отже, це якась кругова залежність, хоча це не так, оскільки властивість / метод статичні. Можливо, помилка, яка виникає в поєднанні з AOT .


У мене це також було, коли є залежність від функції, просто визначеної в одному файлі. Розбивши його на окремий файл, зафіксувавши його.
Джо

1
Дякую, що згадуєте про це. Я опинився в точній ситуації. Я не розумів, що доступ до статичних класів безпосередньо може мати щось спільне з DI. У мене була така схема: A -> Bі обидва вони використовували один і той же статичний клас. Рішення з forwardRefдовідкою, але я буду дивитись, як це можна розв'язати. Я, мабуть, спробую зробити справжній сервіс із цього статичного класу (це також призведе до кращого дизайну).
Слава Фомін II

8

Окрім зниклих @Injectable() декоратора

Відсутній @Injectable()декоратор у абстрактному класі видав Не вдається вирішити всі параметри для обслуговування: (?) Потрібно, щоб він був присутнім, MyServiceяк і у похідному класіBaseService

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

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

7

У моєму випадку це сталося тому, що я не оголосив тип для параметра конструктора.

У мене було щось подібне:

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

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

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

5

для мене це було просто відсутністю ()в @Injectable. Правильним є @Injectable ()


Або в моєму випадку випадково видалити @
TDP

4

Видалення параметрів з методу інжекційного конструктора () вирішило це для мого випадку.


Це була саме моя проблема. Я прийшов, щоб опублікувати це, але виявив, що ти зробив першим! +1
aesede

Тоді як надіслати параметри службі багаторазового використання?
3gwebtrain


2

Ну для мене проблема була ще більше дратує, я користувався сервісом у межах сервісу і забув додати його як залежність у appModule! Сподіваємось, це допоможе комусь заощадити кілька годин, розбиваючи додаток, лише знову створити його


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

2

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

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

2

У моєму випадку передача неправильних параметрів конструктору генерує цю помилку, основне уявлення про цю помилку полягає в тому, що ви несвідомо передали якісь неправильні аргументи будь-якій функції.

export class ProductComponent {
    productList: Array<Product>;

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

Я вирішив це, просто видаливши цей аргумент.


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

У моєму випадку я намагався розширити " NativeDateAdapter", щоб перемогти "format(date: Date, displayFormat: Object) " метод, " метод.

У програмі AngularMaterial-2 DatePicker.

Так я в основному забув додати @Injectableанотацію.

Після того як я додаю це до свого класу "CustomDateAdapter":

@Injectable({
  providedIn: 'root'
})

Помилка пішла.


Це працювало для мене, але я поняття не маю, чому. Чи потрібно надавати і службу, і компонент, який отримує її через DI: In: root, щоб DI працював?
Майк Фурлендер

2

Ця відповідь може бути дуже корисною для цієї проблеми. Крім того, для мого випадку defaultпричиною було експортування послуги .

WRONG:

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

ПРАВИЛЬНО:

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

2

Це може бути дуже важкою проблемою для усунення помилок через відсутність зворотного зв'язку в помилці. Якщо ви стурбовані фактичною циклічною залежністю, ось найголовніше, що слід переглянути в сліді стека: a) ім'я служби; b) параметр конструктора в цій службі, який має знак питання, наприклад, якщо він виглядає так:

не вдається вирішити всі параметри для AuthService: ([Object Object], [object Object], [object Object], [object Object],?)

то це означає, що 5-й параметр - це послуга, яка також залежить від AuthService. тобто знак питання, означає, що він не був вирішений DI.

Звідти вам просто потрібно роз’єднати 2 сервіси шляхом реструктуризації коду.


1

Я зіткнувся з цією помилкою, помиляючи ім'я служби, тобто конструктор (приватна myService: MyService ).

Щодо помилково написаних служб, я зміг визначити, яка служба була проблемою (у конструкторі було декілька), оглянувши сторінку в Chrome-> Console. Ви побачите як частину повідомлення список масиву "параметрів", відобразивши об'єкт Object, object Object,? (або щось подібне). Зауважте, де "?" є і це позиція служби, яка викликає проблему.


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

У моєму випадку я експортував клас та Enum з того самого файлу компонентів:

mComponent.component.ts:

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

Потім я намагався використовувати MyEnumз дитини MyComponentClass. Це спричинило помилку усунення всіх параметрів .

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

Як згадував Гюнтер Зехбауер, це відбувається через те, що послуга або компонент є циркульно залежними.


1

Якщо ваша послуга визначена в тому ж файлі, що і компонент (який її споживає), і служба визначається після компонента у файлі, ви можете отримати цю помилку. Це пов’язано з тим самим питанням "forwardRef", про яке згадували інші. Наразі VSCode не дуже добре показує вам цю помилку і збірка успішно компілюється.

Запуск збірки --aotможе замаскувати цю проблему завдяки тому, як працює компілятор (можливо, це стосується струшування дерев).

Рішення: Переконайтеся, що послуга визначена в іншому файлі або перед визначенням компонента. (Я не впевнений, чи можна в цьому випадку використовувати формат forwardRef, але це здається незграбним).

Якщо у мене дуже простий сервіс, який дуже сильно прив’язаний до компонента (на зразок моделі перегляду) - наприклад. ImageCarouselComponent, Я можу назвати це, ImageCarouselComponent.service.tsщоб він не змішувався з іншими моїми послугами.


1

У моєму випадку це була кругла довідка. У мене було виклик MyService Myservice2 та MyService2, який дзвонив MyService.

Не добре :(


1

У моєму випадку причиною було наступне:

  • мій сервіс для ін'єкцій. Поширений ще один клас B
  • B мав конструктор, який вимагав аргументу
  • Я не визначив жодного конструктора в A

Як наслідок, при спробі створити об’єкт A конструктор за замовчуванням не вдався. Я поняття не маю, чому це не помилка компіляції.

Я вирішив це, просто додавши конструктор в A, який правильно називався конструктором B.


1

Отримав!

Якщо жоден з перерахованих вище відповідей вам не допоміг, можливо, ви імпортуєте якийсь елемент із того самого файлу, куди компонент вводить послугу.

Я пояснюю краще:

Це службовий файл :

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

Таким чином, це створює проблеми, навіть якщо символ знаходиться не в одному компоненті, а просто в одному файлі. Перемістіть символ (це може бути функція, константа, клас тощо) в інше місце, і помилка зникне


1

для кутових 6 та новіших версій спробуйте

@Injectable({
  providedIn: 'root'
})

.. прямо над вашим класом обслуговування, без інших рядків між ними

переваги

  • немає необхідності додавати послугу в будь-який модуль (буде автоматично виявлено)
  • сервіс буде одиночним (оскільки він буде введений в корінь)

[ кутові документи ]

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.