等待订阅完成

时间:2018-08-13 15:20:36

标签: javascript angular rxjs angular-material observable

我有以下代码

this.subscription = this.someService.subscribe((event: FormEvent) => {
    let isConfirmed:boolean;

    this.openDialog();

    const confirmDialogSubscription:Subscription = 
      this.dialogRef.componentInstance.onConfirm.subscribe(() => {
      this.dialogRef.close();
      isConfirmed = true;
    });

    const closeDialogSubscription = 
      this.dialogRef.componentInstance.onClose.subscribe(() => {
      this.dialogRef.close();
      isConfirmed = false;
    });


    //Should be executed after one of these Subscription has fired
    if(isConfirmed){
       //keep on executing
    }
    else{ 
       //stopEvent
       event.preventDefault();
    }
  }
});

目前,我有一个典型的异步问题,即代码不断执行并处理事件。我要等待订阅。

(注意:我正在使用Angular Material对话框并定义了两个Output Event Emitters)

编辑:我的主要问题是,这个“ someService”是我正在使用的库的服务。它为我提供了订阅事件的可能性,但是一旦被触发,它也将成为现实。因此,在我的订阅结束之前,我需要是否调用event.preventDefault()

2 个答案:

答案 0 :(得分:0)

将表达式移动到单独的函数中,并在订阅中调用

Menu1.Controls(i).OnAction = "'SheetChange """ & ws.Name & """'"

答案 1 :(得分:0)

最好将其转变成Observable链-避免在多个地方订阅,只订阅一次整个链:

let evt: FormEvent = null;
this.subscription = this.someService.pipe(
    flatMap((event:FormEvent) => {
        evt = event;
        this.openDialog();
        // Race will emit whichever of the passed observables emits first:
        return race(
            this.dialogRef.componentInstance.onConfirm.pipe(map(() => true)),
            this.dialogRef.componentInstance.onClose.pipe(map(() => false))
        );
    })
).subscribe((confirmed) => {
    if (!confirmed) {
        return evt.preventDefault();
    } else {
       // Call whatever code you wish to continue if confirmed.
    }
});

对于Observables,很少需要为单个逻辑流进行多个订阅-而是总是试图组成一个单个Observable来代表整个功能流,然后订阅一次。

关于异步性问题,请在下面的代码中内联查看我的注释-订阅将始终在您评估是否调用preventDefault的位置触发,并且如果someService中的事件在未阻止的情况下进行处理,相同的堆栈框架,将无法避免:

this.subscription = this.someService.subscribe((event: FormEvent) => {
    let isConfirmed:boolean;

    this.openDialog();

    const confirmDialogSubscription:Subscription = 
      this.dialogRef.componentInstance.onConfirm.subscribe(() => {
      ///// THIS WILL EXECUTE ASYNCHRONOUSLY, SOME TIME LATER
      this.dialogRef.close();
      isConfirmed = true;
    });

    const closeDialogSubscription = 
      this.dialogRef.componentInstance.onClose.subscribe(() => {
      ///// THIS WILL EXECUTE ASYNCHRONOUSLY, SOME TIME LATER
      this.dialogRef.close();
      isConfirmed = false;
    });

    ///// THIS WILL ALWAYS BE EXECUTED BEFORE EITHER OF THE ABOVE
    ///// SUBSCRIPTIONS SO isConfirmed WILL ALWAYS HAVE ITS DEFAULT
    ///// VALUE:    
    //Should be executed after one of these Subscription has fired
    if(isConfirmed){
       //keep on executing
    }
    else{ 
       //stopEvent
       event.preventDefault();
    }
  }
});

唯一的解决方案是使用一个不同的按钮来触发事件,然后,如果用户确认,则手动触发您要控制的事件(如果可能)。