Utilizing Typescript for creating a function to serialize promises

I am in the process of developing a wrapper for promise-returning functions that ensures each call waits for the previous ones to complete before executing.

Although I have a JavaScript implementation available, I am facing challenges in defining the types for the TypeScript implementation. How can I specify the fn parameter as a generic function that returns a promise?

function serializePromises(fn) {
  // This promise initializes our promise queue
  let last = Promise.resolve();
  return function (...args) {
    // Catch is crucial here to prevent a rejection in a promise from disrupting the serialization process indefinitely
    last = last.catch(() => {}).then(() => fn(...args));
    return last;
  }
}

Answer №1

To create a function that can serialize promises, you can utilize two generic type parameters like the example below:

function serializePromises<Args extends unknown[], R extends unknown>(fn: (...args: Args) => Promise<R>) {
  // This acts as our promise queue
  let last = Promise.resolve<null | R>(null);
  
  return function (...args: Args) {
    // Adding a .catch() is crucial here to prevent a rejection in a promise from breaking the serialization process
    last = last.catch(() => null).then(() => fn(...args));
    return last;
  }
}

It is my recommendation to return null instead of leaving it as undefined.

Check out a working example here

Answer №2

This solution is quite effective, although you may observe a few type casts since it's challenging to accurately type let last = Promise.resolve() when it resolves initially without a value.

function batchPromises<TArgs extends Array<unknown>, TReturn extends Promise<unknown>>(fn: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn {
  // The promise queue to handle serialization
  let last: Promise<any> = Promise.resolve();
  return function (...args: TArgs) {
    // We need to use catch here to prevent a rejected promise from breaking the serializer
    last = last.catch(() => {}).then(() => fn(...args));
    return last as TReturn;
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue encountered with redux-toolkit's createAsyncThunk functionality

Here is how I implemented the deleteDirectories method in redux: export const deleteDirectories = createAsyncThunk( "directories/deleteDirectories", async (id, thunkAPI) => { try { const response = await axios.delete(`${url}direc ...

Interactive 3D model movable within designated area | R3F

I am currently facing a challenge in limiting the drag area of my 3D models to the floor within my FinalRoom.glb model. After converting it to tsx using gltfjsx, I obtained the following code: import * as THREE from "three"; import React, { useRe ...

Simplify the cognitive load of the function

I'm facing a challenge with a function that has a cognitive complexity of 24, however, we have a requirement to limit it to a maximum of 15. export function parameterValueParser<T extends Structure>( structure: T ): (parameterValue: Value) =&g ...

The value returned by Cypress.env() is always null

Within my cypress.config.ts file, the configuration looks like this: import { defineConfig } from "cypress"; export default defineConfig({ pageLoadTimeout: 360000, defaultCommandTimeout: 60000, env: { EMAIL: "<a href="/cdn-cgi/ ...

Astro component experiencing script tag malfunction within content collection

I'm trying to create something using a script tag, but for some reason the script doesn't seem to be working properly. Below is my content collection: --- title: Essay Similarity stakeholder: THESIS articleDate: 05 Feb 2023 projectStart: 2022-08 ...

Preventing going back to a previous step or disabling a step within the CDK Stepper functionality

In my Angular application, there is a CdkStepper with 4 steps that functions as expected. Each step must be completed in order, but users can always go back to the previous step if needed. For more information on CdkStepper: https://material.angular.io/cd ...

Definition of type instantiation in TypeScript

When utilizing the mynew function with a specified array of classes, I am encountering an error related to defining unknown. How can I modify this definition in order to eliminate the error? export interface Type<T> extends Function { new (...arg ...

Warning: React Hook Form, NumericFormat, and Material-UI's TextField combination may trigger a reference alert

I'm currently working on a Next.js project using TypeScript and MUI. I'm in the process of creating a form that includes a numeric field for monetary values. In order to validate all fields upon form submission, I have decided to utilize yup, rea ...

Calling the `firstValueFrom()` method in RxJS will keep the observable alive and not

Hey there, I'm currently having issues with using firstValueFrom(), lastValueForm(), and Observable.pipe(take(1)) in my TypeScript code with Angular 14 and RxJs 7.8.0. I am working with a Firebase server that provides stored image URLs via an API wit ...

Guide to incorporating Bootstrap icons into an Angular application through programming techniques

Have you checked out the official bootstrap documentation for information on how to use their icons? https://i.stack.imgur.com/N4z2R.png I'm currently trying to understand the package and its usage. However, none of the options in the documentation ...

Encountering a 404 error when using the NestJS GET function within the service and controller

I am facing an issue with creating simple GET logic. When I test it in Postman, I keep receiving a 404 error. books.service.ts contains the following basic logic: constructor( @InjectRepository(Books) private readonly booksRepo: Repository<Boo ...

What is the right way to configure an Axios Interceptor in a ReactJS app using TypeScript?

While I typically use JS with React, I decided to switch to Typescript. However, I've been encountering an error when trying to initialize a request interceptor instance: src/utils/services/axios.service.ts:16:8 TS2322: Type '{ 'Content-Type ...

What is the recommended approach for testing a different branch of a return guard using jest?

My code testing tool, Jest, is indicating that I have only covered 50% of the branches in my return statement test. How can I go about testing the alternate branches? The code snippet below defines a function called getClient. It returns a collection h ...

Navigating through object keys in YupTrying to iterate through the keys of an

Looking for the best approach to iterate through dynamically created forms using Yup? In my application, users can add an infinite number of small forms that only ask for a client's name (required), surname, and age. I have used Formik to create them ...

Guide on how to utilize jest for mocking MongoDB manager in typescript

Is there a way to return a mongodb.connection.db() type value and mock its collection for testing purposes? I have implemented a mongoClient connection and use its db() function. If everything is set up correctly, I should be able to access the collections ...

Merging RXJS observable outputs into a single result

In my database, I have two nodes set up: users: {user1: {uid: 'user1', name: "John"}, user2: {uid: 'user2', name: "Mario"}} homework: {user1: {homeworkAnswer: "Sample answer"}} Some users may or may not have homework assigned to them. ...

When examining two arrays for similarities

I am dealing with two arrays within my component arr1 = ["one", "two"] arr2 = ["one", "two"] Within my HTML, I am utilizing ngIf in the following manner *ngIf="!isEnabled && arr1 != arr2" The isEnabled condition functions as expected, however ...

Is it possible to use a Jasmine spy on a fresh instance?

In need of assistance with testing a TypeScript method (eventually testing the actual JavaScript) that I'm having trouble with. The method is quite straightforward: private static myMethod(foo: IFoo): void { let anInterestingThing = new Interesti ...

Unlocking the TypeScript UMD global type definition: A step-by-step guide

I have incorporated three@^0.103.0 into my project, along with its own type definitions. Within my project's src/global.d.ts, I have the following: import * as _THREE from 'three' declare global { const THREE: typeof _THREE } Additio ...

What is the equivalent of getElementById in .ts when working with tags in .js?

Looking to incorporate Electron, Preload, Renderer with ReactJS and TypeScript into my project. <index.html> <body> <div id="root" /> <script src='./renderer.js'/> </body> <index.ts> const root = Re ...