【问题标题】:Calling a method which has subscribe how to wait for subscribe return type?调用已订阅的方法如何等待订阅返回类型?
【发布时间】:2020-02-25 02:00:12
【问题描述】:

所以我的问题希望相对容易解决。所以(Angular 8 btw)我调用了一个方法,并在该方法内部订阅了一个 api 调用。一切正常,除了返回总是在方法之后一两秒后被调用,并且返回类型永远不会正确返回。我尝试了 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 };
    });
}

【问题讨论】:

    标签: angular asynchronous rxjs subscription


    【解决方案1】:

    你可以像这样异步调用函数。这会给你一个承诺,需要解决。它将等到得到响应。

    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);
    }
    

    你也可以在这样的一个函数中做同样的事情

    callApi(apiObject) {
      let promise = new Promise((resolve, reject) => {
        let apiURL = `media=music&limit=20`;
        this.http.get(apiURL)
          .toPromise()
          .then(
            res => { 
             // Success
             console.log(res);
             resolve();
            }, (msg) => { 
             // Error
             reject(msg);
            }
          );
      });
      return promise;
     }
    }
    

    【讨论】:

    • 请提及为什么在 SO 中被否决为一个好的姿态?我应该知道原因,因为我们花时间给出完美的答案。
    • 我没有对你投反对票,谢谢你的建议我现在正在尝试,如果我得到你的答案有效,我会标记为已解决:)
    • 如果它适合你,请接受它。是的,有人对此表示反对。这感觉很糟糕,谁只是不理解答案或通过否决答案来表现出愤怒。但是,无论谁投反对票,请评论您所面临的问题。
    • 没用,请记住我是这样使用return的:return this.callApi(apiObject);
    • 你能分享你的整个代码吗?在这里或在 FB 或邮寄给我。我想检查你返回的位置this.callApi( apiObject );分享你返回的方法。
    【解决方案2】:

    如果您想在发出项目时做出反应(基本上是等到检索到数据),最好的办法是在您需要它的组件中订阅,而不是在函数本身中订阅。

    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

    【讨论】:

      【解决方案3】:

      真正的答案是你不能。

      让我重新表述你想要的:你想要一个方法来执行长时间的服务器调用以同步执行。如果可能的话,它会在获得结果所需的 1 秒左右时间内阻止整个应用程序。 整个应用程序,包括浏览器渲染。

      相反,为了使其发挥作用,您必须接受异步性。 不幸的是,这意味着使用未提供的调用 callApi 方法结果的代码。

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

      让我解释一下你的代码中发生了什么,按_执行时间对行进行编号:

      // 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 };
          });
      }
      

      【讨论】:

        猜你喜欢
        • 2021-05-06
        • 1970-01-01
        • 2021-06-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-10
        • 2017-10-08
        • 2019-10-26
        相关资源
        最近更新 更多