Проверять, завершен ли массив Observables синхронно? - PullRequest
0 голосов
/ 25 июня 2018

В моем приложении я бы хотел, чтобы кнопка «Сохранить» ничего не делала, если какие-либо данные в моей форме еще не загружены.Источниками данных в моей форме являются Observables: source1$ и source2$

Поскольку пользователь может в любой момент нажать кнопку, я хочу проверить, ожидают ли какие-либо запросы веб-API иесли они тогда ничего не делают - иначе сохраните.

Я представляю что-то вроде этого:

saveButton_onClicked() {
    if (// source1$ and source2$ are completed) {
        this.saveForm();
    }
}

В любое время любая из этих наблюдаемых может быть назначена новой наблюдаемой (когданапример, данные обновляются), и я не думаю, что forkJoin будет работать здесь, поскольку мне нужно знать в режиме реального времени , должна ли форма быть сохранена или нет, я не хочусобытие щелчка, которое ожидает forkJoin наблюдаемого для разрешения.

Есть идеи?

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

На самом деле, я думаю, что самый простой способ - использовать forkJoin и оператор finalize, а не проверять сами наблюдаемые исходные объекты, а создавать свойство, например.loading, который вы можете проверить в любое время и посмотреть, есть ли ожидаемые наблюдаемые:

whatever() {
  this.loading = true;

  forkJoin(source1$, source2$)
    .pipe(
      finalize(() => this.loading = false)
    )
    .subscribe();
}

saveButton_onClicked() {
  if (!this.loading) {
    ...
  }
}
0 голосов
/ 26 июня 2018

Ну, есть много способов снять кожу с кошки.Некоторые из них более элегантны, чем другие.Я предпочитаю сводить количество дополнительных наблюдаемых свойств к минимуму, который в данном случае кажется равным 2. Я бы добавил свойство isRunningRequest$, чьё значение имеет значение флага, true, если в данный момент выполняются операции.Этот флаг будет дополнен агрегацией по другой наблюдаемой asyncAction$, которая будет использоваться для отслеживания текущих выполняемых действий:

export class AsyncActionData {
  actionType: 'start' | 'end';
  actionToken: string;
}

    public asyncAction$ = new Subject<AsyncActionData>();

    public isRunningRequest$ = new BehaviorSubject<boolean>(false);

    constructor(...) {
        this.asyncAction$
            .pipe(
                // we keep an array of currently running actions, and add
                // or remove from the array according to the action type
                scan((arr: string[], action: AsyncActionData) => {
                    return action.actionType === 'start'
                        ? arr.concat(action.actionToken)
                        : arr.filter(action => action !== action.actionToken);
                }, []),
                map(arr => arr.length === 0 ? false : true)
            )
            .subscribe(requestsAreRunning => this.isRunningRequest$.next(requestsAreRunning));
    }

Когда вы выполняете действие, вы отправляете события на asyncAction$:

this.asyncAction$.next({actionType: 'start', actionToken: 'action1'});
this.http.post(...)
   .subscribe(result => ...,
              null,
              () => this.asyncAction$.next({actionType: 'end', actionToken: 'action1'})
   );

(весь код не проверен, но идея должна быть обоснованной)

См. здесь и здесь для документации по scan оператор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...