简体   繁体   English

NestJS HttpService All Method API 使用Interceptor时调用不起作用

[英]NestJS HttpService All Method API Call is not working when Interceptor is used

NestJS API App use HttpService to call Another API and It works when no custom interceptor is used. NestJS API App 使用 HttpService 调用另一个 API 并且它在没有使用自定义拦截器时工作。 The HttpService API call is executed but it is not reached to another API and could not see the response. HttpService API 调用已执行,但未到达另一个 API 并且看不到响应。

This is get call code这是获取呼叫代码


 get(path: string, body: any = {}): Observable<AxiosResponse<any>> {
    console.log('DomainAPI Response Begining');
    const url = this.baseURL + path;
    this.updateLastUtilizedTimestamp();
    return this.httpService.get(url, { validateStatus: null }).pipe(
      tap(data => {
        console.log('DomainAPI Response Tap', data);
      }),
      retryWhen(
        this.rxJSUtilsService.genericRetryStrategy({
          numberOfAttempts: 3,
          delayTime: 200,
          ignoredErrorCodes: [500],
        }),
      ),
      catchError(this.formatErrors),
    );
  }

if any custom interceptor is used, I found the following when debug.如果使用任何自定义拦截器,我在调试时发现以下内容。

arguments:TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

The Postman shows the following response. Postman 显示以下响应。

{
    "statusCode": 500,
    "message": {
        "Title": "TypeError",
        "Type": "Error",
        "Detail": "Converting circular structure to JSON\n    --> starting at object with constructor 'Observable'\n    |     property 'operator' -> object with constructor 'CatchOperator'\n    --- property 'caught' closes the circle",
        "Status": "Status",
        "Extension": ""
    },
    "timestamp": "Exception - AllExceptionsFilter 2019-12-26T17:29:42.447Z"
}

I changed the above as below but still it is not working我将上面的内容更改如下,但仍然无法正常工作


get(path: string, body: any = {}) {
    console.log('DomainAPI Response Begining');
    const url = this.baseURL + path;
    this.updateLastUtilizedTimestamp();
    return this.httpService.get(url, { validateStatus: null }).pipe(
      map(response => {
        console.log('DomainAPI Response Tap', response.data);
        return response.data;
      }),
    );
  }

It gives the following response in the postman它在 postman 中给出以下响应


{
    "data": {
        "_isScalar": false,
        "source": {
            "_isScalar": false,
            "source": {
                "_isScalar": false
            },
            "operator": {}
        },
        "operator": {}
    }
}

Please advise请指教

async get(path: string, body: any = {}): Promise<any> {
    ...
    const res = await this.httpService.get(url, { validateStatus: null }).toPromise();

    return res.data;
  }
get(path: string, body: any = {}) {
   ...
    return this.httpService.get(url, { validateStatus: null })
    .toPromise()
    .then(res => res.data)
    .catch(err => this.logger.error(err));
  }

Converting to a promise using the.toPromise() method has been deprecated because we are working with observables and a promise returns only one value while observables could return no value or more that one value (see more @: Conversion to Promises ).使用 .toPromise() 方法转换为 promise 已被弃用,因为我们正在使用可观察对象,并且 promise 仅返回一个值,而可观察对象可能不返回任何值或返回多个值(参见更多@:转换为承诺)。 So as an example using the question above the solution would be:因此,作为使用上述问题的示例,解决方案将是:

import { lastValueFrom } from 'rxjs';

get(path: string, body: any = {}): Observable<AxiosResponse<any>> {
    console.log('DomainAPI Response Begining');
    const url = this.baseURL + path;
    this.updateLastUtilizedTimestamp();
 
    return await lastValueFrom(
      this.httpService.get(url, { validateStatus: null })
      .pipe(
      tap(data => {
        console.log('DomainAPI Response Tap', data);
      }),
      retryWhen(
        this.rxJSUtilsService.genericRetryStrategy({
          numberOfAttempts: 3,
          delayTime: 200,
          ignoredErrorCodes: [500],
        }),
      ),
      catchError(this.formatErrors),
    ));
  }

Basically all you have to do is wrap the whole http request with firstValueFrom or lastValueFrom, in this case lastValueFrom is what would be appropriate.基本上你所要做的就是用 firstValueFrom 或 lastValueFrom 包装整个 http 请求,在这种情况下 lastValueFrom 是合适的。 Visit the link to the documentation on Conversion to promises above by rxjs to know more about this.请访问 rxjs 上面关于转换为承诺的文档的链接,以了解更多信息。

NOTE: I added just the lastValueFrom import only as a clear indicator of what is needed.注意:我只添加了 lastValueFrom 导入,只是作为所需内容的明确指示。

This is another example using my own code:这是使用我自己的代码的另一个示例:

async send_otp(
    phone: string,
    channel: string,
    ): Promise<Observable<AxiosResponse<any>>> {
    return await lastValueFrom(
      this.httpService
        .post(`/messaging/otp/`, {
          sender: 'Oyinkayy',
          destination: '234' + String(phone).slice(1),
          length: 6,
          channel: channel,
          reference: '',
        })
        .pipe(
          tap((resp) => console.log(resp)),
          map((resp) => {
            return resp.data;
          }),
          tap((data) => console.log(data)),
          catchError(async (err) => {
            return err;
          }),
        ),
    );
   }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM