Exploring the creation of a personalized throttling function using TypeScript

My current function is functioning perfectly:

do {
    try {
        const { assets } = await myApi(arg1, arg2, arg3);     <<--  
        return assets; 
    } catch (err: any) {
        if (err.response.status == 429) {
            await sleep(300);
            console.log('Throttle occurred, sleeping for 300ms');
        } else
            throw (err);
    }
}
while (true);

I aim to generalize this method and invoke it like so:

throttleHandler(myApi, ...args)

I made a few attempts but TypeScript raised some issues. I'm uncertain about the correctness of my approach and prefer not to use any. It's important for me to ensure types are defined.

type ThrottleHandler<TOut> = (...args: any) => TOut;

async function throttleHandler<T>(promiseFunction: ThrottleHandler<T>, ...args: any): Promise<T> {
  console.log("args", args, ...args)
  do {
    try {
      return await promiseFunction(...args);
    } catch (err: any) {

      if (err.response.status == 429) {
        await sleep(300);
        console.log('Throttle occurred, sleeping for 300ms');
      } else
        throw (err);
    }
  }
  while (true);
}

Answer №1

interface PromiseFunction {
    (...args: any[]): Promise<any>;
}

type ReturnType<T extends PromiseFunction> = T extends (...args: any[]) => Promise<infer R> ? R : any;

async function handleThrottle<ApiFn extends PromiseFunction>(
    promiseFunction: ApiFn,
    ...args: Parameters<ApiFn>
): Promise<ReturnType<ApiFn>> {
    console.log("Arguments:", args, ...args);
    
    do {
        try {
            return await promiseFunction(...args);
        } catch (err: any) {
            if (err.response.status == 429) {
                await sleep(300);
                console.log('Request throttled, waiting for 300ms');
            } else {
                throw err;
            }
        }
    } while(true);
}

const sampleFn = (arg1: string, arg2: number) => {
    console.log(arg1);
    return Promise.resolve(true);
}

const result = handleThrottle(sampleFn, 'param', 12);

This updated version removes the use of TS 4.5's Awaited type, making it compatible with recent TypeScript versions.

Playground Link

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

Setting up a Form submit button in Angular/TypeScript that waits for a service call to finish before submission

I have been working on setting up a form submission process where a field within the form is connected to its own service in the application. My goal is to have the submit button trigger the service call for that specific field, wait for it to complete suc ...

What is the best way to retrieve the current time from an angular material Date picker?

I'm currently utilizing the Angular Material datepicker component found at https://material.angular.io/components/select/overview However, it seems to only display the date without the current time: Mon May 28 2018 00:00:00 GMT+0530 (IST) Is there a ...

React TSX file not recognizing JSON data stored in an HTML data attribute

I am having some trouble with implementing the password toggle component from the Preline UI. Here is how the component looks: "use client" import React, { ChangeEvent, MouseEventHandler, useEffect } from "react"; export default functi ...

Utilizing Dependency Injection with TypeScript and Angular 5 in an Abstract Class

In my BaseComponent, I have some dependencies injected. The first dependency, EntityService, is essential and correctly implemented. However, the AnyOtherService is only utilized within the abstract BaseComponent. Instead of injecting it into the ChildCom ...

Utilize fixed values in type declaration

Strange Behavior of Typescript: export type MyType = 0 | 1 | 2; The above code snippet functions correctly. However, the following code snippet encounters an issue: export const ONE = 1; export const TWO = 2; export const THREE = 3; export type MyType = O ...

Hiding loading spinner in Ionic 2 upon iframe completion

I need to embed an external webpage in my app using an iframe. I have successfully implemented a loading animation while the iframe is loading, but I am unsure how to hide the animation once the iframe content has loaded. Unfortunately, I am unable to edit ...

Discovering the ReturnType in Typescript when applied to functions within functions

Exploring the use of ReturnType to create a type based on return types of object's functions. Take a look at this example object: const sampleObject = { firstFunction: (): number => 1, secondFunction: (): string => 'a', }; The e ...

Typescript KeyboardEvent bug: incorrect initialization of keys

I'm trying to generate a KeyboardEvent in my Typescript code. const arrowLeft = new KeyboardEvent('keydown', { key: 'ArrowLeft' }); console.log(arrowLeft.keyCode, arrowLeft.key, arrowLeft.code); When I check the value of arrowLef ...

Issue a tslint warning when mockResolvedValueOnce is used with async/await

While working with the request-promise module, everything seems to be functioning correctly except for a warning from tslint. Below is my unit test: import * as request from 'request-promise'; jest.mock('request-promise', () => { ...

Transform Typescript code into Javascript using webpack while preserving the folder organization

Is there a way for webpack to compile my typescript node project into js while preserving the directory structure and not bundling into one file? This is my current project structure: src |_controllers |_home |_index.ts |_ services ...

Issue with manipulating element styles using jQuery in Angular2

My method of assigning IDs to elements dynamically using *ngFor looks like this: <div *ngFor="let section of questionsBySubCat" class="col-md-12"> <div class="subcat-container"> <h4 class="sub-cat">{{ section?.subcategory }}& ...

React Native Component Error: Cannot read property '_this' of undefined

I am currently developing a face recognition application using React Native 0.63. I'm running my project using react-native run-android. However, I encountered an issue with Component Exception where it shows 'undefined is not an object (evaluati ...

Issue with Value Update in Angular 7 Reactive Forms

I am encountering an issue where the data in my formgroup does not update upon submission. The formgroup successfully retrieves values from an API, but when attempting to update and return the value, it remains unchanged. I am unsure of what mistake I may ...

Spread an all-encompassing category across a collection

What is the method in TypeScript to "spread" a generic type across a union? type Box<T> = { content: T }; type Boxes<string | number> = Box<string> | Box<number>; (Given that we are aware of when to use Boxes versus Box) ...

The spread operator seems to be malfunctioning whenever I incorporate tailwindcss into my code

Hi there! I hope you're doing well! I've come across a strange issue in Tailwindcss. When I close the scope of a component and try to use props like ...rest, the className doesn't function as expected. Here's an example: import { Butto ...

Issue with ion-select default value not being applied

In my ion-select element, I have multiple options and I want to set a default value based on the CurrentNumber when the view is loaded. Here's the code snippet: <ion-select formControlName="Level"> <ion-option [value]="level.id" *n ...

Customize nestjs/crud response

For this particular project, I am utilizing the Nest framework along with the nestjs/crud library. Unfortunately, I have encountered an issue where I am unable to override the createOneBase function in order to return a personalized response for a person e ...

Sending input in a nested event listener

I am currently utilizing Highcharts for the purpose of showcasing an interactive map with custom countries. I have a specific requirement to enable the drilldown functionality, which involves clicking on a country to zoom in on another map displaying inter ...

Caution in NEXTJS: Make sure the server HTML includes a corresponding <div> within a <div> tag

Struggling with a warning while rendering pages in my Next.js and MUI project. Here's the code, any insights on how to resolve this would be greatly appreciated! import "../styles/globals.scss"; import { AppProps } from "next/app"; ...

Steps to modify the CSS of a custom component in Angular 8

I have been attempting to override the css of a custom component selector, however, my attempts have been unsuccessful. I have tried using ":ng-deep" but it hasn't worked. How can I go about finding a solution for this issue? app.component.html: < ...