Можно ли использовать одноразовую подписку на действие http в службе Angular? Есть ли какой-либо недостаток в этом?
public async signInAsync(userName: string, password: string): Promise<void> {
try {
const token = await this.authenticate(userName, password).pipe(first()).toPromise();
this.signInCompleted(token);
} catch {
this.signInFailed();
}
}
Для того чтобы использовать стратегию обнаружения изменений OnPush и также сохранить «бизнес-логику» внутри сервисов, сервисы используют наблюдаемую функцию, называемую state$
, для предоставления значений компонентам, а затем компоненты подписываются на это значение с помощью асинхронного канала. Только функции сервиса могут обновлять состояние, вызывая this.patchState('actionName', {...})
.
protected signInCompleted(token: string): void {
this.localStorageService.setItem(LocalStorageKey.AUTH_TOKEN, token);
this.patchState('signInCompleted', {
isAuth: true,
token: token,
error: null
});
this.router.navigate([AppRoute.AUTH]);
}
Поэтому, если я использую HttpClient, я должен каким-то образом подписаться на возвращаемое наблюдаемое.
Я начал с простой подписки:
protected signIn(...): void {
this.authenticate(..).subscribe(..);
}
Но потом я понял, что это не поддается тестированию, потому что я не знаю, когда выполняется вызов, а async()
не знает о наблюдаемом.
Чтобы он был тестируемым, мне нужно было сделать его асинхронным и преобразовать в обещание, однако я не уверен, есть ли какой-либо недостаток, если я подпишусь на pipe(first()).toPromise()
.
Я также думал об использовании pipe(map(...)).pipe(catchError(...))
, но я не знаю, как затем связать действие с компонентом или лучше, чем предыдущий подход.
public signIn(userName: string, password: string): Observable<void> {
return this.authenticate(userName, password).pipe(map(...)).pipe(catchError(...));
}