【问题标题】:How to use rxjs/Observables inside Nestjs Application w/o Controller如何在不带控制器的 Nestjs 应用程序中使用 rxjs/Observables
【发布时间】:2022-01-19 12:59:35
【问题描述】:

Nestjs suggests 使用从 @nestjs/axios 导入的 HttpModule 来执行对外部 API 的请求。 我了解HttpService 将响应转换为Observables

目标

从外部 API 请求数据并在应用程序内部使用数据。

问题

我不明白如何从请求中实际检索数据。我在其他一些答案中读到,如果您从 Controller 返回 observable,Nestjs 会自动为您处理它并将数据返回给客户端。这很好,但是,我没有在 Controller 中使用它。我需要数据在应用程序中可用。

我有一个服务:

@Injectable()
export class ExampleService {

  // constructor

  getData(): Observable<AxiosResponse<any[]>> {
    return this.httpService.get(`http://some-url.com`);
  }

}

如何在应用程序逻辑中使用getData() 来获取Observable 返回的数据?在这种情况下,使用带有Promises 的普通axios 请求而不使用HttpModule 会更好吗?

目前我发现的唯一解决方案是使用subscribe

this.httpService.get(`http://some-url.com`)
.subscribe((value) => {
  console.log(value);
});

与所有花哨的async ... awaits相比,这似乎最终会陷入回调地狱。

【问题讨论】:

  • 您可以拨打getData订阅。 this.service.getData().subscribe
  • 这与调用httpService.get().subscribe 相同,我已将其包含在我的问题中。

标签: axios rxjs nestjs


【解决方案1】:

答案

目前我发现的唯一解决方案是使用订阅

宾果游戏。就这样完成了:)

一些阐述

与所有花哨的异步...等待相比,这似乎最终会陷入回调地狱

不是真的。作为一个为声明式而构建的库,RxJS 可以轻松构建回调。

async/await 只是 promises 和 .then 的语法糖。这是一种语言特性,但即使没有 async/await 承诺也能很好地相互绑定,避免深度嵌套和“回调地狱”

因此,虽然 observables 不(也可能永远不会)喜欢像 async/await 这样的一流语言结构,但这并不意味着它们不会为您管理一些(或很多)复杂性。


RxJS 库的构建使得通常您不必嵌套订阅。

以下被认为是反模式:

stream1().subscribe(value1 => 
  stream2(value1).subscribe(value2 => {
    /* Do something with value2 */
  })
)

它会更习惯地写成:

stream1().pipe(
  mergeMap(value1 => stream2(value1))
).subscribe(value2 => {
  /* Do something with value2 */
})

注意如何删除缩进级别并且您只需要订阅一次?

Observables 带有一组高阶运算符,它们充当高度可定制的.thens 值流,而不仅仅是单个值。

另一种方式:转换为 Promise

Observable 是 Promise 的超集,这意味着您可以将任何 Promise 转换为 Observable,但如果您想将 Observable 转换为 Promise,则会失去结构。通常这不是问题,但让我通过类比来解释。

如果 promise 是一个值的容器,那么 observables 就是一个值列表的容器。

我可以取任何值并从中创建一个列表。我只会有一个长度为 1 的列表。

value = 5
// convert with:
list_values = [a]

我无法从任何列表中创造价值。我可以取第一个值,或者最后一个值(如果只有一个,那可能是相同的),如果列表为空,也许我需要抛出一个错误?也许有一个我会满意的默认值?

也许我有办法将多个值减少为一个值。也许我可以通过将整数列表加在一起来将它们变成一个值。

list_values = [1,2,3,4,5]
// convert with:
value = list_values[0] || 0
// or
value = list_values[list_values.length - 1] || 100
// or
value = sum(list_values)

回到承诺。 RxJS 有 firstValueFromlastValueFrom 作为实用函数,它们将 Promise 包装在 observable 周围。

firstValueFrom(
  this.httpService.get(`http://some-url.com`)
).then(value => {
  /* Do something with value */
});

// or with await as syntactic sugar

value = await lastValueFrom(
  this.httpService.get(`http://some-url.com`)
);
/* Do something with value */

这些对于像 http 请求这样的东西通常就足够了(因为它们只返回一个值)。更复杂的方法倾向于在转换为 Promise 之前在 RxJS 端处理。

【讨论】:

  • 感谢@MrkSef 提供了非常丰富的答案!这让我对如何处理这个问题有了更好的了解。我肯定会检查 firstValueFrom ,就像你说的,这些对于 http 请求可能已经足够了。
猜你喜欢
  • 2020-09-30
  • 2021-08-02
  • 2016-04-27
  • 2019-11-14
  • 1970-01-01
  • 2019-04-09
  • 2020-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多