Angular - вызов функции dealy, пока тема не завершена - PullRequest
0 голосов
/ 14 июня 2019

У меня есть функция, которая отменяет запущенный процесс с некоторыми processId.Существует только один if оператор , перед которым проверяется, есть ли у вас processId, и если да, то он вызывает cancel().

if (this.processId) {
  //...
  this.processEngine.cancel(this.processId, this.entityUid).subscribe(
    ...
  );
} else {
  console.log('No active process to cancel');
}

. При запуске процесса отображается экран загрузки.с анимацией загрузки и кнопкой Cancel .Теперь существует проблема, заключающаяся в том, что в течение очень короткого момента (в основном при регулировании с помощью инструментов dev) пользователь может нажать Cancel , и processId еще не был инициализирован, и, таким образом, процесс запуска не отменен.

В службе есть Subject, для которого установлено значение processId при успешном запуске процесса и его немедленном завершении после этого.

private startSubject = new Subject<string | null>();
...
// inside start function
this.startSubject.next(processId);
this.startSubject.complete();

Существует также BehaviorSubject, который имеет значение true, когда проект запущен и работает.

active: BehaviorSubject<boolean> = new BehaviorSubject(false);

Я расширил оператор if с помощью this.active.value, но я не могу понять, как отложить отмену вызова, пока startSubject не будет завершено.Я попытался использовать его в debounce, но он не работает должным образом, и метод отмены вызывается с undefined, что приводит к ошибке.

this.processEngine.cancel(this.processId, this.entityUid).pipe(
  debounce(() => 
    return this.startSubject.asObservable()
  )
)
.subscribe(...);

1 Ответ

1 голос
/ 15 июня 2019

Если я правильно понял ваше требование, то это то, чего вы хотите достичь -

Ничего не должно происходить при нажатии кнопки "Отмена", пока "processId" не станет нулевым.

Если мое понимание верно, то вы можете сделать следующее -

//have a Behavior subject to track processId
processId$: BehaviorSubject<any> = new BehaviorSubject<any>(null);

//create the cancel button click observable
this.cancelClick$ = fromEvent(this.button.nativeElement, 'click');

//have a notnull processid observable
//it will ensure that only not null value will be emited
const notNullProcessId$ = this.processId$.pipe(filter(processId => !!processId));

//compose above both observables
//What will happen - 
//If you click "cancel" button nothing will happen
//as soon as your processId is emitting non null value, and then user clicks cancel your cancel API will be called
//it is just a basic - You can now code your API not to do cancel if process is already cancelled etc...
notNullProcessId$.pipe(
                  switchMap((processId) => {
                    return this.cancelClick$
                               .pipe(
                                 switchMap(() => {
                                   return this.processEngine.cancel(processId, this.entityUid);
                                 })
                               );
                  })                      
                ).subscribe(cancelResult => {
                  //do whatever you want to do wth cancel result
                  console.log(cancelResult);
                });

//This function will be called by your consumer who sets the processId
emitValue(processId) {
    this.processId$.next(processId);
    this.processId$.complete();
  }

Дайте мне знать, если это работает в вашем сценарии.

...