Внедренный сервис не определен прямо в конструкторе
К сведению, я совершенно не связан с Angular (1 или 2 в этом отношении).
Я пытаюсь написать "супер" слой Http, чтобы избежать необходимости помещать одинаковые заголовки везде.
import {Http, ConnectionBackend, RequestOptions, Response, Headers} from '@angular/http';
import {Observable} from 'rxjs';
import {LoadingService} from "../../services/loading.service";
export class HttpLoading extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions,
private _ls: LoadingService )
{
super(backend, defaultOptions);
}
getPostPutHeader() {
var authHeader = new Headers();
authHeader.append("Authorization", "Bearer "+ localStorage.getItem('token') );
authHeader.append('Content-Type', 'application/json');
return authHeader;
}
post(url: string, data:any):Observable<Response> {
this._ls.isLoading = true; // Exception here: this._ls is undefined
return super.post(url, data, { headers: this.getPostPutHeader() })
.map(res => {
this._ls.isLoading = false;
return res;
});
}
}
И сервис, чтобы сказать, когда запрос выполняется; это вводится в вышеупомянутый класс HttpLoading.
import {Injectable} from '@angular/core';
@Injectable()
export class LoadingService {
isLoading: boolean = false;
}
У меня есть куча вещей в моей начальной загрузке, включая HttpLoading, LoadingService и ConnectionBackend (для этого последнего я получаю исключение, если его здесь нет).
bootstrap(AppComponent, [
ConnectionBackend,
HttpLoading,
APP_ROUTER_PROVIDERS,
HTTP_PROVIDERS,
LoadingService,
disableDeprecatedForms(),
provideForms()
])
Проблема в том, что первый раз звоню HttpLoading
"s post
метод (в еще одном сервисе), я получаю исключение в this._ls.isLoading
, так как this._ls
не определено, и я не могу понять, почему.
Пожалуйста, скажите мне, если вам нужна дополнительная информация.
редактировать
LoadingService
правильно вводится в моем AppComponent
(главный компонент).
//imports
//@Component
export class AppComponent {
requesting:boolean = false;
constructor(public authService: AuthService, private router: Router, private _ls: LoadingService) {
}
navigate(route:string) {
this._ls.isLoading = true;
this.router.navigate([route])
.then(() => this._ls.isLoading = false);
}
}
Потенциальное решение
Похоже, что ваши публичные / приватные параметры должны быть на первом месте в списке. Я позволю кому-то более опытному, чем я, объяснить, почему, хотя...
export class HttpLoading extends Http {
constructor(private _ls: LoadingService, backend: ConnectionBackend, defaultOptions: RequestOptions) {
super(backend, defaultOptions);
}
3 ответа
Я бы настроил ваш HttpLoading
Классифицируйте этот способ в поставщиках при загрузке вашего приложения:
bootstrap(AppComponent, [
(...)
HTTP_PROVIDERS,
{
provide:Http,
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, loadingService: LoadingService) => {
return new HttpLoading(backend, defaultOptions, loadingService);
},
deps: [XHRBackend, RequestOptions, LoadingService]
}
]);
Причина этого в том, что вы хотите использовать свой собственный класс для провайдера Http. Вам нужно изменить класс за провайдером Http вашим HttpLoading
учебный класс. Будьте осторожны, чтобы определить его после HTTP_PROVIDERS
,
Чтобы иметь возможность внедрить экземпляр XHRBackend
к вашему классу, вы должны использовать useFactory
...
Хорошо, я знаю, что это может показаться тривиальным, но попробуйте создать переменную и инициализировать ее в конструкторе
Чтобы расширить ответ @Thierry Templier. Я использую Angular v4, и мой опыт показывает, что вам нужно предоставить ВСЕ зависимости, которые нужны вашему расширяющему конструктору, И в правильном порядке - я полагаю, это устаревший способ сделать это, начиная с angular 1.x.
Мой пример:
// Это мой расширенный класс (только соответствующая часть)
@Injectable()
export class HttpService extends Http {
constructor(
backend: ConnectionBackend,
defaultOptions: RequestOptions,
private router: Router,
private loaderService: LoaderService,
private modalService: ModalService,
private localStorageService: LocalStorageService
)
{
super(backend, defaultOptions)
}
// Это фабрика провайдеров, определенная в app.module.ts:
export function httpClientFactory(
backend: XHRBackend,
defaultOptions: RequestOptions,
router: Router,
loaderService: LoaderService,
modalService: ModalService,
localStorageService: LocalStorageService
) : Http
{
return new HttpService(
backend,
defaultOptions,
router,
loaderService,
modalService,
localStorageService
);
}
Это конфигурация (только что оставленная соответствующая часть) в app.module.ts:
providers: [
ModalService
LocalStorageService,
LoaderService,
{
provide: HttpService,
useFactory: httpClientFactory,
deps: [XHRBackend, RequestOptions, Router, LoaderService, ModalService, LocalStorageService]
}
Примечание: обратите внимание на порядок объявления deps в конфиге по сравнению с конструктором фабрики.. это то же самое