Zbudowałem podstawową aplikację w Angular 2, ale napotkałem dziwny problem, w którym nie mogę wstrzyknąć usługi do jednego z moich komponentów. Jednak wstrzykuje się dobrze w którykolwiek z trzech innych komponentów, które stworzyłem.
Na początek jest to usługa:
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;
}
}
A komponent, z którym odmawia współpracy:
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);
}
}
Występuje błąd w konsoli przeglądarki:
WYJĄTEK: nie można rozwiązać wszystkich parametrów dla HeaderComponent: (?).
Mam usługę w funkcji bootstrap, więc ma dostawcę. I wydaje mi się, że jestem w stanie wstrzyknąć go do konstruktora dowolnego z moich innych komponentów bez problemu.
angular
angular2-di
Keith Otto
źródło
źródło
'../'
index.ts
Odpowiedzi:
Zaimportuj go z pliku, w którym jest zadeklarowany bezpośrednio zamiast beczki.
Nie wiem, co dokładnie powoduje problem, ale widziałem to kilka razy (prawdopodobnie pewną zależność cykliczną).
Powinien być również naprawiony poprzez zmianę kolejności eksportu w beczce (nie znam szczegółów, ale został również wspomniany)
źródło
2.0.2
). Uważam, że beczki są nadal przydatne, zwłaszcza gdy muszę zaimportować kilka modeli i usług między różnymi modułami. Toimport { cleanValues, getState, FirebaseService, NotificationService, ... } from '../../shared/services';
był ból, kiedy to nie działało (;NgModule
nie pomaga w usługach singletonowych ...Oprócz wcześniejszych odpowiedzi wydaje się, że ten błąd jest zgłaszany również wtedy, gdy usługa wstrzykiwania nie ma rzeczywistego
@Injectable()
dekoratora. Dlatego przed debugowaniem kwestii cyklicznej zależności i kolejności importu / eksportu należy po prostu sprawdzić, czy usługa faktycznie@Injectable()
zdefiniowała.Dotyczy to aktualnej wersji Angular, Angular 2.1.0.
Otworzyłem problem w tej sprawie .
źródło
Router
z „@ angular / router” i bez tego iniekcji ten błąd będzie się zawsze pojawiał (jak tylko zdecydujesz się wprowadzić jedną linię użyj kodu, który wstrzyknął router@injectable()
nie jest wymagane. Co jest kolejną osobliwością samą w sobie. Na wszelki wypadek nadal to dodam, po prostu na czas, kiedy powinieneś zdecydować się na zastrzyk.Od Angular
2.2.3
dostępna jest terazforwardRef()
funkcja narzędzia, która pozwala wstrzykiwać dostawców, którzy nie zostali jeszcze zdefiniowani.Przez niezdefiniowane rozumiem, że mapa wstrzykiwania zależności nie zna identyfikatora. Tak dzieje się podczas zależności cyklicznych. W Angular możesz mieć zależności kołowe, które bardzo trudno jest rozplątać i zobaczyć.
Dodanie
@Inject(forwardRef(() => MobileService))
do parametru konstruktora w kodzie źródłowym pierwotnego pytania naprawi problem.Bibliografia
Instrukcja Angular 2: ForwardRef
Przekaż referencje w Angular 2
źródło
forwardRef()
był już w wersji alfa ;-) Jest potrzebny tylko wtedy, gdyMobile
usługa jest zadeklarowana w dalszej części tego samego pliku. Jeśli klasy znajdują się w różnych plikach, nie ma potrzebyforwardRef()
forwardRef()
pomogłem pozbyć sięCan't resolve all parameters for ...
wiadomości. Przynajmniej składnik działa, kiedy szukam lepszego rozwiązania problemu. (I tak, zależność od awarii jest importowana bezpośrednio z jej pliku)forwardRef
. Bardzo trudno go znaleźć. Wczoraj zajęło mi cały dzień, aby rozwiązać ten problem.foreardRef
siebie, ale już nie późniejNgModule
. Nie martwię się o utratę przedstawicieli. Jestem tylko ciekawy, dlaczego się na to natknąłeś, gdy nie pojawił się już od kilku miesięcy. Przyjrzę się bliżej, kiedy wrócę do domu za kilka dni. Wielkie dzięki za opinie.ŹLE # 1: Zapominanie o Dekoratorze:
ŹLE # 2: Pominięcie symbolu „@”:
ŹLE # 3: Pominięcie symboli „()”:
ŹLE # 4: Małe litery „i”:
ŹLE # 5: Zapomniałeś: import {Injectable} z '@ angular / core';
POPRAWNY:
źródło
Jak już wspomniano, problem jest spowodowany zamówieniem eksportu w beczce, który jest spowodowany zależnościami cyklicznymi.
Bardziej szczegółowe wyjaśnienie znajduje się tutaj: https://stackoverflow.com/a/37907696/893630
źródło
Zetknąłem się również z tym, wstrzykując usługę A do usługi B i odwrotnie.
Myślę, że to dobrze, że szybko się to nie udaje, bo i tak powinno się go unikać . Jeśli chcesz, aby Twoje usługi były bardziej modułowe i nadawały się do ponownego wykorzystania, najlepiej unikać w miarę możliwości odwołań cyklicznych. Ten post podkreśla pułapki, które go otaczają.
Dlatego mam następujące zalecenia:
EventService
), którą obie usługi mogą wprowadzić w celu wymiany wiadomości.źródło
Z korzyścią dla poszukiwaczy; Mam ten błąd. To był po prostu brakujący symbol @.
Tj. To powoduje
Can't resolve all parameters for MyHttpService
błąd.Dodanie brakującego
@
symbolu naprawia go.źródło
W moim przypadku musiałem dodać
import "core-js/es7/reflect";
do mojej aplikacji, aby@Injectable
działać.źródło
Inną możliwością nie jest
emitDecoratorMetadata
ustawienie wartości true w pliku tsconfig.jsonźródło
Ten błąd występuje, jeśli masz usługę A, która zależy od właściwości statycznej / metody usługi B, a sama usługa B zależy od wstrzyknięcia zależności usługi A do koryta. Jest to więc rodzaj zależności cyklicznej, chociaż nie jest tak, ponieważ właściwość / metoda jest statyczna. Prawdopodobnie błąd występujący w połączeniu z AOT .
źródło
A -> B
obaj używali tej samej klasy statycznej. RozwiązanieforwardRef
pomaga, ale przyjrzę się, jak można to rozwiązać. Prawdopodobnie postaram się zrobić prawdziwą usługę z tej klasy statycznej (doprowadzi to również do lepszego projektu).Oprócz brakujących
@Injectable()
dekoratoraBrak
@Injectable()
dekoratora w klasie abstrakcyjnej spowodował, że nie można rozwiązać wszystkich parametrów usługi: (?) Dekorator musi być obecnyMyService
zarówno w klasie pochodnej, jak iBaseService
źródło
W moim przypadku stało się tak, ponieważ nie zadeklarowałem typu parametru konstruktora.
Miałem coś takiego:
a następnie zmiana go na poniższy kod rozwiązała mój problem.
źródło
dla mnie był to po prostu brak
()
w @Injectable. Prawidłowe jest @Injectable ()źródło
Usunięcie parametrów z metody iniekcji konstruktora () rozwiązało to w moim przypadku.
źródło
W moim przypadku było to spowodowane wtyczką Augury, wyłącz to będzie działać poprawnie. Alternatywną opcją jest aot, działa również.
wszystkie kredyty @ Boboss74, opublikował odpowiedź tutaj: https://github.com/angular/angular/issues/23958
źródło
Cóż, dla mnie problem był jeszcze bardziej irytujący, korzystałem z usługi w ramach usługi i zapomniałem dodać ją jako zależność w module aplikacji! Mam nadzieję, że pomoże to komuś zaoszczędzić kilka godzin na zerwaniu aplikacji, ale tylko do jej ponownego utworzenia
źródło
@Inject
adnotacji. Przeoczyłem dokładnie to, co mówi komunikat o błędzie. Jeśli nie podejrzewasz zależności cyklicznych, po prostu przejdź do klasy wymienionej w błędzie i spójrz na wszystkie parametry konstruktora i wszystkich członków klasy opatrzonych adnotacjami@Inject
i upewnij się, że wykonujesz DI na wszystkich z nich. Więcej na temat DI tutaj: angular.io/docs/ts/latest/guide/dependency-injection.htmlMusisz dodać tablicę dostawców w dekoratorze @Component lub w module, w którym deklarowany jest twój komponent. Wewnątrz komponentu możesz wykonać następujące czynności:
źródło
W moim przypadku przekazanie niewłaściwych parametrów do konstruktora generuje ten błąd, podstawową ideą tego błędu jest to, że nieświadomie przekazałeś jakieś nieprawidłowe argumenty do dowolnej funkcji.
Rozwiązałem to, po prostu usuwając ten argument.
źródło
Dla mnie ten błąd wystąpił, gdy przez pomyłkę wyłączyłem ten import w pliku polyfills.ts, musisz się upewnić, że został zaimportowany, aby uniknąć tego błędu.
źródło
W moim przypadku próbowałem przedłużyć „
NativeDateAdapter
”, aby zastąpić ”format(date: Date, displayFormat: Object)
metodę metodę ”.W AngularMaterial-2 DatePicker.
Zasadniczo więc zapomniałem dodać
@Injectable
anotację.Po dodaniu tego do mojej klasy „CustomDateAdapter”:
Błąd zniknął.
źródło
Ta odpowiedź może być bardzo pomocna w przypadku tego problemu. Ponadto w moim przypadku eksport usługi
default
był przyczyną.ŹLE:
POPRAWNY:
źródło
Może to być bardzo trudny problem do debugowania z powodu braku informacji zwrotnej w błędzie. Jeśli obawiasz się o faktyczną zależność cykliczną, oto najważniejszą rzeczą, na którą należy zwrócić uwagę w stosie a) nazwa usługi b) parametr konstruktora w tej usłudze, który ma znak zapytania, np. Jeśli wygląda tak:
oznacza to, że piąty parametr jest usługą zależną również od usługi AuthService. tzn. znak zapytania oznacza, że nie został rozwiązany przez DI.
Stamtąd wystarczy oddzielić 2 usługi, restrukturyzując kod.
źródło
Wystąpił ten błąd przez błędne wpisanie nazwy usługi, tj. Konstruktora (private myService: MyService ).
W przypadku usług z błędami pisarskimi byłem w stanie ustalić, która usługa była problemem (miałem kilka wymienionych w konstruktorze), sprawdzając stronę w Chrome-> Console. Zobaczysz jako część wiadomości listę tablic „parametrów”, wyświetlając obiekt Obiekt, obiekt Obiekt,? (czy jakoś tak). Zauważ, gdzie „?” jest i to jest pozycja usługi, która powoduje problem.
źródło
Chociaż zamawianie można było wspomnieć eksportowanych klas z beczek, poniższy scenariusz może również dać ten sam efekt.
Załóżmy, że masz zajęcia
A
,B
iC
wywożone ze w tym samym pliku, gdzieA
zależyB
iC
:Ponieważ klasy zależne (tj. W tym przypadku klasy
B
iC
) nie są jeszcze znane Angularowi ( prawdopodobnie w czasie wykonywania podczas procesu wstrzykiwania zależności Angulara do klasyA
) błąd jest zgłaszany.Rozwiązanie
Rozwiązaniem jest zadeklarowanie i wyeksportowanie klas zależnych przed klasą, w której wykonano DI.
tzn. w powyższym przypadku klasa
A
jest zadeklarowana zaraz po zdefiniowaniu jej zależności:źródło
W moim przypadku eksportowałem klasę i enum z tego samego pliku komponentu:
mComponent.component.ts
:Potem próbowałem użyć
MyEnum
od dziecka zMyComponentClass
. To spowodowało błąd Nie można rozwiązać wszystkich parametrów .Przeniesienie
MyEnum
do osobnego folderu odMyComponentClass
rozwiązało mój problem!Jak wspomniał Günter Zöchbauer, dzieje się tak, ponieważ usługa lub komponent jest zależny cyklicznie.
źródło
Jeśli twoja usługa jest zdefiniowana w tym samym pliku co składnik (który ją zużywa), a usługa jest zdefiniowana później komponencie w pliku, możesz otrzymać ten błąd. Wynika to z tego samego problemu „forwardRef”, o którym wspominali inni. W tej chwili VSCode nie jest świetny w pokazywaniu tego błędu, a kompilacja się kompiluje.
Uruchomienie kompilacji
--aot
może maskować ten problem ze względu na sposób działania kompilatora (prawdopodobnie związany z drżeniem drzewa).Rozwiązanie: Upewnij się, że usługa jest zdefiniowana w innym pliku lub przed definicją komponentu. (Nie jestem pewien, czy w tym przypadku można użyć forwardRef, ale wydaje się to niezdarne).
Jeśli mam bardzo prostą usługę, która jest bardzo mocno związana z komponentem (coś w rodzaju modelu widoku) - np.
ImageCarouselComponent
, Mogę to nazwać,ImageCarouselComponent.service.ts
żeby nie pomieszało się z moimi innymi usługami.źródło
W moim przypadku było to okrągłe odniesienie. Miałem MyService dzwoniąc do Myservice2 i MyService2 dzwoniąc do MyService.
Niedobrze :(
źródło
W moim przypadku powodem było:
W rezultacie próba utworzenia obiektu A nie powiodła się domyślny konstruktor. Nie mam pojęcia, dlaczego nie był to błąd kompilacji.
Naprawiłem to, dodając konstruktor w A, który poprawnie nazwał konstruktorem B.
źródło
Gotcha!
Jeśli żadna z powyższych odpowiedzi nie pomogła, być może importujesz jakiś element z tego samego pliku, w którym składnik wstrzykuje usługę.
Wyjaśniam lepiej:
To jest plik usługi :
To jest plik komponentu :
Powoduje to problemy, nawet jeśli symbol nie znajduje się w tym samym komponencie, ale tylko w tym samym pliku. Przenieś symbol (może to być funkcja, stała, klasa itd.) W inne miejsce, a błąd zniknie
źródło
dla wersji kątowej 6 i nowszych spróbuj
.. tuż nad klasą usług, bez żadnych innych linii pośrednich
Zalety
[ dokumenty kątowe ]
źródło