Search code examples
javascripttypescriptaxiosnestjs

Nestjs HttpException filter don't handle my throw for a axios request catch block


I'm trying to make an axios request inside a array.map , for each map item i need to make a axios request and save some response info. When i'm using my code logic all errors handled in my catch block can't make a throw HttpException inside my catch block since it doesn't send my error back to my nestjs filter.

I'm using a axios interceptor in my main.ts file, the error goes to my interceptor in main.ts and my code breaks.

Service example code and result(postman don't receive nothing)

 async fetchData() {
    try {
    const numbers = [ 1 , 2 , 3 ,4 , 5, 6]
    const mapReturn = numbers.map( async (numero) => {
    return 
this.
  httpService.
  axiosRef.get('http://10.55.110.10:7076/axios/test')
  
   })
     
 } catch (err) {
  console.log('catch console.log')
    throw new HttpException('testando' , 409)
}
}

this axios request only returns throw httpException

above code console

  filter console.log
  main console.log
   node:internal/process/promises:289
        triggerUncaughtException(err, true /* fromPromise */);

   HttpException: Conflict
     at <anonymous> (/var/www/html/api_testes/src/main.ts:28:13)
     at process.processTicksAndRejections 
  (node:internal/process/task_queues:95:5)
    at Axios.request
   at process.processTicksAndRejections 
  (node:internal/process/task_queues:95:5) {
  response: 'Conflict',
  status: 409,
   options: undefined
 }

   Node.js v20.11.1

axios interceptor in main.ts

 httpService.axiosRef.interceptors.response.use(
async (response) => {
  return response;
},
async (error) => {
  const { status , statusText } = error.response;
  console.log('main console.log')
  throw new HttpException(statusText, status)    },
 );

my httpException filter (default filter from nestjs docs)

@Catch(HttpException)
 export class HttpExceptionFilter 
  implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
  console.log('filter console.log')
  const ctx = host.switchToHttp();
  const response = ctx.getResponse<Response>();
  const request = ctx.getRequest<Request>();
  const status = exception.getStatus();

  response
    .status(status)
    .json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }
}

Without the map in the function my code work's like i intended and my console only returns the console.log my interceptor and filter sends

I'm expecting to throw an httpException and my filter handles the error so the code don't crash


Solution

  • First of all, you need a Promise.all to wait for all requests to finish. Also you may add a catch to handle each request error individually, if needed. Here's how it might look:

    async fetchData() {
      try {
        const numbers = [1, 2, 3, 4, 5, 6];
        const requests = numbers.map(number => 
          this.httpService.axiosRef.get('http://10.55.110.10:7076/axios/test')
            .catch(error => {
              console.log(`Error for number ${number}:`, error.message);
              throw new HttpException(`Failed request for ${number}`, error.response?.status || 500);
            })
        );
        return await Promise.all(requests);
      } catch (err) {
        console.log('Outer catch block:', err);
        throw new HttpException('Something went wrong', 500);
      }
    }
    

    For your Axios interceptor in main.ts, you can keep it simple and use Promise.reject, or also throw error:

    httpService.axiosRef.interceptors.response.use(
      response => response,
      error => {
        console.log('main console.log', error)
        // Option 1: return Promise.reject(error);
        // Option 2: throw error; 
        // Option 3: Use your current implementation also should be fine "throw new HttpException(statusText, status);"
      }
    );
    

    Using Promise.reject(error) is generally better because it keeps the error in the promise chain, allowing you to handle it where you made the request. This gives you more control and context for error handling.

    Throwing the error directly (throw error) can work, but it might lead to unhandled promise rejections if you're not careful. It can also make debugging trickier because the error won't be caught in the place you expect.