【问题标题】:NestJS HttpService call multiple endpointsNestJS HttpService 调用多个端点
【发布时间】:2020-04-16 15:26:56
【问题描述】:

我通常是一名 PHP 开发人员,几乎没有使用 javascript/typescript 的经验。刚开始使用 NestJS - 我想要一个端点,它返回一个 requisitions 列表,该列表是通过其端点从另一个系统检索到的。

粗略的想法:

  1. 使用凭据调用登录端点
  2. 使用来自登录端点的令牌调用 requisition 列表端点
  3. 返回结果

我已经尝试过像这样调用端点:

const url ='https://the-requisition-endpoint';
const config: AxiosRequestConfig = {
      headers: {
        'Accept': 'application/json',
        'Authorization': 'a_hard_coded_token_string' // hard coded for experimentation
      }
    };
let result = this.httpService.get(url, config);
result.subscribe(response =>
  console.log(response.data);
});

现在我需要更改它,以便令牌不会被硬编码 - 以使用来自登录端点的令牌。

我不确定如何强制仅在登录端点返回令牌后才调用申请端点。我搜索并发现Promise.all() 或a function called zip might help, 但我不知道如何使它工作。

【问题讨论】:

    标签: typescript axios nestjs


    【解决方案1】:

    我相信您正在寻找的 RxJS 运算符是 switchMap。本质上,您最终会想要做这样的事情:

    @Injcetable()
    export class MyService {
    
      constructor(private readonly httpService: HttpService) {}
    
      getRequisitions(): Observable<any> {
        // change to POST signature is login is a post. post(url, body, config)
        return this.httpService.get(url, config).pipe(
          // optional, but it makes working with responses easier
          map(resp => resp.data),
          // make new http call and switch to this observable
          switchMap(loginData => this.httpService.get(url, configWithLoginData)),
          / again, optional, but useful for keeping data easily readable
          map(resp => resp.data),
          // optional, but useful for checking what is returned
          tap(data => console.log(data))
      }
    }
    

    好的,这里发生了很多事情,所以让我们也分解一下。在 NestJS 中,内置的 HttpService 返回 Observables 而不是 Promises。这允许您执行一些非常强大的操作,例如在出现某些故障时重试 HTTP 调用。这可以通过 Promise 完成,但确实需要更多代码。无论如何,在第一次 HTTP 调用之后的.pipe 允许我们开始操作 RxJS 流并处理通过的数据。

    map 是一个 RxJS 运算符,类似于 Array.prototype.map 运算符,因为它对 observable 发出的每个值应用一个转换函数(在这种情况下,它只是一个值,但理论上它可以适用于许多)。

    switchMap 是 RxJS 中的扁平化运算符之一,还有 mergeMap 和 concatMap。我会让你从与上面相同的链接中阅读这些内容,但本质上,switchMap 取消了当前的 observable 以支持新创建的 observable,这有助于我们避免内存泄漏。我们返回一个新的 Observable(一个新的 HttpService 调用),并开始使用该数据。

    tap 是一个间谍操作员,因为它不会对其有权访问的数据做任何事情,它只是允许您查看它(通过 console.log)。这几乎是它的用途,但如果需要并且响应无关紧要,您可以进行其他标注。

    最后,没有subscribe,因为 NestJS 将在后台订阅并将最后发出的值作为响应发送。我们自己不用担心。

    哦,所有map(resp =&gt; resp.data) 的响应是AxiosResponse 有几个字段,但在大多数情况下,您可能只关心data 属性中保存的返回数据。

    每个 RxJS 运算符都接受一个函数,我们在这里的每种情况下都只使用一行函数。如果需要,您可以使用完整的匿名函数语法。即

    map((resp) => {
      return resp.data;
    })
    

    单行语法更短,但如果必须执行不适合一行的附加逻辑,则需要重写。

    【讨论】:

    • 您好,感谢您的回复和链接,非常有帮助。但是有一个问题,我如何“执行”整个事情?我有这样的东西:let requisitionData = this.login().pipe( ...,然后当我做console.log(requisitionData); 时,它说它是一个 Observable。
    • 如果这是针对 HTTP 响应,即控制器调用的某些服务,您可以只返回 Observable 并让 NestJS 在后台订阅。如果这是手动执行,您可以添加 .subscribe({ next: (val) =&gt; void, error: (err) =&gt; void, complete: () =&gt; void})(这些是签名,您可以根据需要使用它们,只要确保它们返回 void)并查看 next 函数中返回的值。你可以在我的服务器中看到一些more rxjs sample。还可以查看测试以查看订阅
    猜你喜欢
    • 2021-12-10
    • 2019-01-25
    • 2022-01-25
    • 2011-11-26
    • 2019-08-21
    • 2019-08-31
    • 2020-06-23
    • 2021-12-21
    • 2021-02-06
    相关资源
    最近更新 更多