Состояние обновления RxJS и сквозная передача - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть пользовательская библиотека, которая используется в нескольких приложениях 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 для остального управления состоянием.При использовании моей библиотеки мы замечаем некоторые странности:

  1. При нахождении внутри эффекта ngRx иногда любые функции, использующие HttpClient Angular, будут вызываться несколько раз.Чтобы устранить эту проблему, любая функция, которую я использую HttpClient, оканчивается на .publishLast().refCount(), чтобы гарантировать, что HTTP-вызов выполняется только один раз.

  2. В случае сбоя вызова потребитель не может перехватитьисключение.Например, 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()))
      })
    )
  );

1 Ответ

0 голосов
/ 03 декабря 2018

После вызова события subscribe оно запускается, и результат разрешается (правильный результат или ошибка) в методе подписки.Поэтому в тот момент, когда вы вызываете метод this.authService.getProfile().catch, асинхронное событие уже запущено и завершено.Вот почему он не вызывает.

Вы можете либо переместить оператор catch в getProfile, либо вы можете вернуть наблюдаемое из getProfile, не подписываясь на него.

public getProfile(url: string): Observable<User> {
    return this._http.get<User>(url)
            .pipe( tap( profile => this.setProfile(profile))); 
}

Теперь подпишитесь на него через сервис authService

this.authService.getProfile()
  .subscribe(profile =>  // do the work)
  .catch(error => alert(error))
...