首页 > 解决方案 > Node.js/NestJS:强制执行 HTTP 调用(使其成为更热的 Observable)

问题描述

我正在为一些最终用户开发一个库,通过 HttpService 调用 API ,最终用户将使用或不使用其结果。

        end-user consumer <==> my library <=(HTTP)=> remote API

现在 HttpService 使用冷 Observables,这意味着只有当我们订阅生成的 Observable 时它才会触发 HTTP 调用。如果我将此 Observable 返回给我的最终用户,并且他们不订阅它,因为在他们的特定用例中他们不需要结果,则永远不会调用 API。

出于这个原因,我倾向于在将 Observable 返回给最终用户之前先订阅它,但我不确定它是一个优雅或安全的解决方案,因此这篇文章。我的代码如下所示(为帖子简化,并使用来自@nestjs/common 的 HttpService):

ServiceToAccessAPIData.ts

export class ServiceToAccessAPIData {
  ...
  callToEndPoint(): Observable<any> {
    const obs = httpService.get(someUrl)
    .pipe(
      shareReplay(1) // see A
    );

    obs.subscribe(()=>{},()=>{}); // see B

    return obs;
  }
  ...
}

和:

现在,对于这样一个微不足道的用例来说,这似乎有点复杂:“为最终用户提供一种安全的方式来拨打电话,无论他们是否使用结果”

有没有更好、更简单、更优雅的方式来做到这一点?

此外,在性能方面,这种技术会有什么结果吗?

HttpService Observers 只发出一次然后完成,因此订阅将自动“取消订阅”。但我想知道 shareReplay 观察到的底层 Observer 会变成什么。我想当我返回的 Observable 不再引用它时,它将被垃圾收集,但我想知道。


使用 Promises(由 MoazzamArif 建议)

上面的问题仍然存在(特别是如果需要坚持使用 Observables),但最初问题的解决方案可能是使用.toPromise()作为返回给最终用户的值。

return obs.toPromise();

.toPromise() 订阅Observable(让它立即执行 HTTP 调用)并将其包装在 Promise 中,一旦 Observable 完成(在 HttpService 的情况下,只要API 返回了一个结果)。

=> 这实际上满足了“为最终用户拨打电话提供安全的方式,无论他们是否使用结果”的需求。

现在让我们进一步挖掘。我想这是一个需要考虑的异国情调和奇怪的场景,但我们如何处理这种情况:

=> 因为.toPromise()直接订阅 Observable,但没有提供错误处理程序,错误会冒泡并导致应用崩溃

=> 如果我们直接链接.catch(err => anyValue)到返回的 Promise,错误将被捕获,但最终用户将在 .then() 中收到anyValue 并且无法处理原始错误

=> 如果我们直接链接.catch(err => { someHandling(); return Promise.reject(err); }到返回的 Promise,因为用户还没有链接他们的.catch(),来自新拒绝的 Promise 的新错误将冒泡并导致应用程序崩溃

因此,我认为没有解决方案,并且上述情况根本无法处理(可以使用 Observable .shareReplay(1) 解决方案来处理它)。

标签: node.jsnestjshttpservice

解决方案


推荐阅读