У меня есть пользовательская библиотека, которая используется в нескольких приложениях Angular в моей организации.В качестве рефакторинга / новой версии мы стремимся перейти к службе на основе состояния с интерфейсом, подобным следующему:
export interface UserService {
user: Observable<User>
getProfile(url: string): Observable<User>
updateProfile(url: string): Observable<User>
}
Таким образом, потребители могут связывать компоненты с UserService.user
, зная, чтоданные всегда будут актуальными и вызывать функции get / update в кнопках или в фоновом режиме и т. д.
Уточнение: Пользовательская библиотека предназначена для использования в приложениях, которые используютngRx
, а также тех, кто не хочет что-то тяжелое, но все же хочет привязку пользователя на основе наблюдаемых.
Поэтому я подключаю функции следующим образом (с небольшими изменениями):
public getProfile(url: string): Observable<User> {
const obs = this._http.get<User>(url);
obs.subscribe(profile => this.setProfile(profile));
return obs;
}
Где setProfile
обновляет внутреннюю подписку, которую UserService.user
возвращает только для чтения.
Однажды мои потребительские приложения используют ngRx
для остального управления состоянием.При использовании моей библиотеки мы замечаем некоторые странности:
При нахождении внутри эффекта ngRx
иногда любые функции, использующие HttpClient
Angular, будут вызываться несколько раз.Чтобы устранить эту проблему, любая функция, которую я использую HttpClient
, оканчивается на .publishLast().refCount()
, чтобы гарантировать, что HTTP-вызов выполняется только один раз.
В случае сбоя вызова потребитель не может перехватитьисключение.Например, this.authService.getProfile().catch(error => alert(error))
никогда не будет вызвано.Чтобы обойти это, я теперь изменяю свои функции по их подписке: obs.subscribe(profile => this.setProfile(profile), error => Observable.throw(error));
Это нормальное поведение при реализации службы "state-store" в Angular?
Редактировать: Пример эффекта ngRx (обратите внимание, что это реальная реализация, то, что я разместил выше, значительно упрощено от нашей реальной реализации):
public BiographyUpdate: Observable<any> = this._actions.pipe(
ofType(AuthActionTypes.BIOGRAPHY_UPDATE),
map((action: BiographyUpdate) => action.payload),
switchMap(bio => this._auth.update(`${Environment.Endpoints.Users}/users/sync/biography`, action)
.map(profile => new BiographyUpdateSuccess(profile.biography))
.catch(error => {
console.log("AM I BEING HIT?");
return Observable.of(new BiographyUpdateFailure(error.toString()))
})
)
);