【问题标题】:Subject subscribe, wait until function execution finished主题订阅,等待函数执行完成
【发布时间】:2020-10-09 20:56:23
【问题描述】:

我对 observables 有一个问题。我的情况是,我订阅了主题,我想在成功的可观察响应中运行一个函数。一旦我的函数(foo)完成(这个函数必须完成才能在成功响应中继续逻辑),我想将 .next() 方法传递给我的另一个主题。我的问题是,我想不通,我怎么能等到我的函数 foo 完成并返回值。如果我在另一个主题上调用 setTimeout 到我的 .next() 方法,则一切正常。我只是想避免 setTimeout。 我的代码架构是:

this.customService.customSubject$.subscribe((response) => {
  this.someValueNeededInFoo = response;    
  this.foo(); //I need to wait for this function to be executed until I move on
  this.customService2.anotherSubject$.next(true); //That will be great if I can wait for this as well
  this.customService2.thirdSubject$.next(response); //This should invoke last
});

foo() {
 //do some logic stuff 
 return value;
}

如果我像这样在订阅中使用我的代码:

this.customService.customSubject$.subscribe((response) => {
      this.someValueNeededInFoo = response;
      this.foo(); //I need to wait for this function to be executed until I move on
      
      setTimeout(() => {
      this.customService2.anotherSubject$.next(true); //That will be great if I can wait for this as well
      this.customService2.thirdSubject$.next(response); //This should invoke last
      }, 1000);
      
    });

然后一切正常。我想避免 setTimeout,因为在我的情况下它并不可靠。任何人都可以指导我,我可以在这里做什么,以进行这些函数调用链? 谢谢!

【问题讨论】:

    标签: asynchronous rxjs


    【解决方案1】:

    您的问题不在于可观察对象,而在于 this.foo() 是一个异步方法,这意味着它返回一个承诺。

    您可以在调用foo() 之后将您的逻辑简单地放在.then() 块中。这确保它在 foo 完成后执行:

    this.customService.customSubject$.subscribe(response => {
      this.someValueNeededInFoo = response;    
      this.foo().then(valFromFoo => {
         this.customService2.anotherSubject$.next(true);
         this.customService2.thirdSubject$.next(response);
      })
    });
    

    您可以选择使用async/await 语法,而不是使用.then()。下面的代码等价于上面的例子:

    this.customService.customSubject$.subscribe(async response => {
      this.someValueNeededInFoo = response;    
      await this.foo();
      this.customService2.anotherSubject$.next(true);
      this.customService2.thirdSubject$.next(response);
      })
    });
    

    我想提一下,通常没有必要创建一堆主题来从其他流中发出值。您通常能够定义彼此的流。

    而不是做这样的事情:

    docIdSubject$ = new Subject<string>();
    documentSubject$ = new Subject<Document>();
    
    this.someService.id$.subscribe(
      id => this.docIdSubject$.next(id)
    );
    
    this.docIdSubject$.subcribe(
      docId => {
        this.docService.getDocument(docId).subscribe(
          document => this.documentSubject$.next(document)
        );
      );
    );
    

    您可以从源 observable 中定义您的 observable,根本不需要主题。

    docId$ = this.someService.id$;
    document$ = this.docId$.pipe(
       switchMap(id => docService.getDocument(id))
    );
    

    您可以根据需要使用可管道运算符来转换您的流。请注意,没有内部订阅。我发现将所有数据转换逻辑以声明方式放在流定义中(在.pipe() 中)会更简洁,在实际订阅中几乎不需要做任何工作。

    现在请注意,您可以使用document$.subscribe()

    【讨论】:

    • 这有帮助吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    • 2015-09-16
    • 2021-11-16
    • 1970-01-01
    相关资源
    最近更新 更多