NestJS HTTP Promise Module with Retries

4.0.0 · active · verified Wed Apr 22

nestjs-http-promise is a NestJS module that extends the framework's official HTTP capabilities by providing a promise-based API for Axios-powered requests. This library, currently at version 4.0.0, aims to simplify HTTP client interactions by eliminating the need for explicit `.toPromise()` calls on RxJS Observables, which are typically returned by NestJS's default HttpModule. A key differentiator is its out-of-the-box integration of automatic request retries using `axios-retry` and enhanced Axios stack traces for improved debugging. The package generally follows major NestJS and Axios version updates, ensuring compatibility with the latest ecosystem features. It offers both static and asynchronous configuration options, allowing for flexible setup within various NestJS architectural patterns. Its primary function is to provide a more imperative, promise-centric approach to HTTP requests within a declarative NestJS module structure, contrasting with the Observable-first approach of the base NestJS HTTP module.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to install, configure (asynchronously), inject, and use `nestjs-http-promise` to perform promise-based HTTP requests with built-in retries, fetching and creating a test post.

import { Module, Injectable, INestApplication } from '@nestjs/common';
import { HttpModule, HttpService, HttpModuleOptionsFactory, HttpModuleOptions } from 'nestjs-http-promise';
import { NestFactory } from '@nestjs/core';

// Example of an async configuration service
@Injectable()
class HttpConfigService implements HttpModuleOptionsFactory {
  async createHttpOptions(): Promise<HttpModuleOptions> {
    // Simulate fetching configuration data asynchronously, e.g., from a config service or environment variables
    const configurationData = await Promise.resolve({
      baseURL: 'https://jsonplaceholder.typicode.com',
      timeout: 5000,
      maxRetries: 3,
      isBetterStackTraceEnabled: true // Enable improved stack traces by default
    });

    return {
      baseURL: configurationData.baseURL,
      timeout: configurationData.timeout,
      retries: configurationData.maxRetries,
      isBetterStackTraceEnabled: configurationData.isBetterStackTraceEnabled,
    };
  }
}

@Injectable()
class MyApiService {
  constructor(private readonly httpService: HttpService) {}

  /**
   * Fetches a post by ID. This call benefits from the module's configured retries.
   */
  async fetchPost(id: number): Promise<any> {
    console.log(`Attempting to fetch post ${id}...`);
    // The HttpService methods return Promises directly
    const response = await this.httpService.get(`/posts/${id}`);
    return response.data;
  }

  /**
   * Creates a new post. Retries can be overridden per request.
   */
  async createPost(title: string, body: string): Promise<any> {
    console.log('Attempting to create a new post...');
    const response = await this.httpService.post('/posts', { title, body, userId: 1 }, {
      retries: 0 // No retries for create operations for this specific request
    });
    return response.data;
  }
}

@Module({
  imports: [
    // Asynchronously configure HttpModule using a factory class
    HttpModule.registerAsync({
      useClass: HttpConfigService,
    }),
  ],
  providers: [MyApiService, HttpConfigService], // HttpConfigService must be provided if used with useClass
  exports: [MyApiService], // Export the service if it's used by other modules
})
class ApiIntegrationModule {}

async function bootstrap() {
  const app: INestApplication = await NestFactory.create(ApiIntegrationModule);
  await app.listen(3000, () => {
    console.log('NestJS Application listening on port 3000');
  });

  const apiService = app.get(MyApiService);

  try {
    const post = await apiService.fetchPost(1);
    console.log('\nFetched Post 1:', post);

    const newPost = await apiService.createPost('Hello Registry', 'This is a test post from the registry quickstart.');
    console.log('\nCreated New Post:', newPost);
  } catch (error: any) {
    console.error('\nAn error occurred during API calls:');
    console.error('Error message:', error.message);
    if (error.response) {
      console.error('Response status:', error.response.status);
      console.error('Response data:', error.response.data);
    } else if (error.code === 'ECONNABORTED') {
      console.error('Request timed out or cancelled.');
    }
  } finally {
    await app.close();
    console.log('\nApplication closed.');
  }
}

// To run this quickstart, save it as a .ts file in a NestJS project and execute with `ts-node` or compile.
// In a real application, `bootstrap()` would be called from `main.ts`.
bootstrap();

view raw JSON →