Angular-Dealy函数调用,直到主题未完成

时间:2019-06-14 13:15:54

标签: angular typescript rxjs observable

我有一个函数可以取消某些processId的运行进程。只有一个 if语句,在此之前检查您是否有processId,如果有,则调用cancel()

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

启动该过程时,将显示一个带有加载动画和 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);

我用this.active.value扩展了 if语句,但我不知道如何将取消呼叫推迟到startSubject未完成之前。我尝试在反跳中使用它,但是它没有按预期工作,并且用undefined调用cancel方法导致错误。

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

1 个答案:

答案 0 :(得分:1)

如果我正确理解了您的要求,那么这就是您想要实现的-

单击“取消”按钮,直到"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();
  }

让我知道它是否适用于您的情况。