调用具有订阅的方法如何等待订阅返回类型?

时间:2019-10-29 19:17:28

标签: angular asynchronous rxjs subscription

所以我的问题希望解决起来相对简单。因此(Angular 8 btw)我调用一个方法,并且在该方法内部我订阅了api调用。一切正常,除了return总是在方法之后的一两秒钟被调用,并且return类型永远不会正确返回。我尝试了MAP,但无法正常工作。让我编写一个简单的示例:

return this.callApi( apiObject ); // I want to wait for subscribe and return data here

callApi( apiObject ) {
  this.myApiService.someRandomPostApiCall( apiObject ).subscribe(res => {
            console.log(res);
            res.valid ? { return true } : { return false };
    });
}

3 个答案:

答案 0 :(得分:1)

如果要在发出项目时做出反应(基本上等到检索到数据),那么最好的选择是在所需的组件中进行订阅,而不是在函数本身中进行订阅。

return this.callApi( apiObject ).subscribe(//do stuff here);

callApi( apiObject ) {
  return this.myApiService.someRandomPostApiCall( apiObject )
}

这是我的一个应用程序中的一个示例:

在服务中

  getProducts(): Observable<IProduct[]> {
    return this.http.get<IProduct[]>(this.productUrl)
      .pipe(
        tap(data => console.log('All: ' + JSON.stringify(data))),
        catchError(this.handleError)
      );
  }

在组件中

  ngOnInit(): void {
    this.productService.getProducts().subscribe({
      next: products => this.products = products,
      error: err => this.errorMessage = err
    });
  }

您可以在此处查看整个源:

https://stackblitz.com/edit/github-angular-getting-started-final

答案 1 :(得分:0)

真正的答案是你做不到。

让我改一下您想要的内容:您希望有一个方法可以执行长时间的服务器调用以同步执行。如果可能的话,它将阻塞整个应用程序大约1秒钟,以获取结果。 整个应用程序,包括浏览器渲染。

相反,为了使其工作,必须拥抱异步性。 不幸的是,这意味着要处理占用了callApi方法结果的代码,而未提供该代码。

如果您能提供,我们可以推理出完成这项工作的最佳方法。

让我解释一下您的代码中发生了什么,以_execution时间对行进行编号:

// I'm splitting the rows, just to better describe the order of execution
const somethingThatYouDonTExpect = this.callApi(apiObject);  // this runs first
return somethingThatYouDonTExpect;  // this runs third, returning a subscription object

callApi(apiObject) {
  // this runs second and returns IMMEDIATELY a subscription object, NOT a result
  return this.myApiService.someRandomPostApiCall( apiObject ).subscribe(res => {
            console.log(res); // this runs fourth, and the return is completely useless: subscribe is not expected to return anything.
            res.valid ? { return true } : { return false };
    });
}

答案 2 :(得分:-1)

您可以像这样异步调用该函数。这将给您带来诺言,需要解决。它将等待直到得到响应。

{
  author: {
    name: "hehyryg",
    titles: ["title", "title2"]
  }
}

现在您这样称呼

callApi(apiObject) {
   return new Promise((resolve, reject) => {
       this.api.someRandomPostApiCall(apiObject).subscribe(res => {
           if (res.valid) {
                  resolve({status: true});
                }
         }, (error) => {
            resolve({status: false});
         },
         () => {

          });
       });
 }

或者这样

// starts here
this.callApi(apiObject).then((res) => {
// ends here
    console.log(res);
   return res;
});

您也可以在一个函数中执行相同的操作

async getData() { 
  return await this.callApi(apiObject);
}