How can the map function be executed sequentially every second, using async functions, fetch API, and promises, without running in parallel?

I am facing an issue with my map function, as it needs to fetch data from an online API that only allows one request per second. I attempted to solve this problem by implementing the following code:

const sleep = (ms: number) => {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
};

const promises = projectData.map(async (project, index) => {
        return await getAddress(asdf)
          .then((nominatimData) => {
        // ....perform some actions...
          })
          .catch(async (e) => {
            console.log("failed", e);
            return await sleep(2000).then(() => {
              console.log("retrying... ")
              return getAddress(asdf);
            });
          });
    });

    await Promise.allSettled(promises);

    console.log("Project Data", projectData); //fires before all getAddress() are retrieved.. :(

I am encountering two challenges that I cannot resolve:

  1. It seems like the map() function is executing in parallel (is this accurate?), which is not ideal for me because I need it to run sequentially, with a one-second delay between requests.

  2. My sleep function does not appear to be functioning correctly. The console log output is disorganized and simultaneous.

What would be the best approach to ensure that this code executes once every second? Is there a better way to handle retrying "getAddress" if it fails?

Thank you for your assistance!

Answer №1

In response to your query:

  1. Indeed, the map function does not wait for the Promise to complete before moving on to the next operation. However, you can address this issue by utilizing a for loop.
  2. By using map to run the operations, your sleep function executes concurrently for every element in the array. While the logic is sound, there may be room for improvement in terms of methodology.

You have the option to employ a for loop that supports async/await functionality. Nonetheless, considering that you aim to await a server response, I would suggest implementing a custom cursor loop instead.

let cursor = 0;
const timeout = 1000;
const sleep = (ms) => {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
};

const loop = async () => {
    // Stop if index goes out of bounds
    if (!projectData[cursor]) {
        return console.log('Done');
    }

    await getAddress(projectData[cursor]).then(async (nominatimData) => {
        // ....perform necessary actions...
        // Move on to the next element in the array
        cursor++;
        await loop();

    }).catch(async (e) => {
        console.log(`Failed, retrying in ${ timeout }ms`);
        await sleep(timeout);
        await loop(); // Retry the loop with the same cursor index
    });
};
await loop();

Answer №2

setTimeout() is a handy function that runs once, with a specified delay. On the flip side, setInterval() continuously executes its contents in a loop, at set intervals.

For more information, you can visit the documentation links here: setTimeout() and setInterval()

To automate fetching API data, consider using setInterval() to enclose your code snippet like this:

setInterval(() => {    
  your code here
}, 1000);

Feel free to adjust the interval time (1000ms or 1s) as needed.

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

A generic type in TypeScript that allows for partial types to be specified

My goal is to create a type that combines explicit properties with a generic type, where the explicit properties have priority in case of matching keys. I've tried implementing this but encountered an error on a specific line - can anyone clarify why ...

Utilizing shared state in React components through props

Currently, I am utilizing a shared global state in the following manner: interface DashboardProps extends React.Props<Dashboard> { globalState? : GlobalState } export class Dashboard extends React.Component<DashboardProps, any>{ } Withi ...

Combining TypeScript into HTML resulted in an error: Uncaught ReferenceError clickbutton is not defined

Attempting to create a basic CRUD frontend without the use of any frameworks. I am encountering an issue when trying to include a TypeScript file (index.ts) in my index.html, as the functions called within it are showing as undefined. I understand that bro ...

Why is it that I am limited to running globally installed packages only?

Recently, I made the switch to Mac iOS and encountered an issue while setting up a new TypeScript backend project. All npm packages seem to be not functioning properly in my scripts. Cannot find module 'typescript/bin/tsc' Require stack: - /Users ...

Tips for identifying unnecessary async statements in TypeScript code?

We have been encountering challenges in our app due to developers using async unnecessarily, particularly when the code is actually synchronous. This has led to issues like code running out of order and boolean statements returning unexpected results, espe ...

How to transfer a parameter in Angular 2

I am currently facing a challenge in passing a value from the HTML file to my component and then incorporating it into my JSON feed URL. While I have successfully transferred the value to the component and displayed it in the HTML file, I am struggling to ...

Angular 2 partial static routing parameters with customizable features

Can an angular 2 routing configuration include a partial-static parameter? Currently, I am using a classic parameter setup like this: const routes: Routes = [ { path: ':type/fine.html', pathMatch: 'full', redirectTo: &ap ...

TS7053: The element is implicitly assigned an 'any' type as the expression of type 'string' cannot be used to index the type '{ username: string; email: string; '

Having trouble incorporating TypeScript into a custom React Form Component, and I keep encountering an error that I can't seem to resolve. Error message TS7053: Element implicitly has an 'any' type because expression of type 'string&apo ...

Manipulating Data in TypeScript: Creating a Mutated Copy of a List of Dictionaries

After going through multiple answers, it appears that there might be a logical error. However, I am struggling to find a solution for this issue. In TypeScript/JavaScript, I have two lists of dictionaries. One list is a copy of the other for tracking purp ...

Different Angular 2 components are resolved by routes

Consider this scenario: Upon navigating to the URL /product/123, the goal is to display the ProductComponent. This is how it's currently configured: RouterModule.forRoot([ { path: 'product/:productId', ...

The 'HTMLDivElement' type does not include the property 'prepend' in Typescript

When working with a typescript method, the following code snippet is used: some_existing_div.prepend(some_new_div) This may result in an error message: [ts] Property 'prepend' does not exist on type 'HTMLDivElement'. However, despi ...

How do I retrieve a specific svg element in Angular among multiple elements?

I recently delved into learning Angular for a new project. One of my main objectives was finding a way to dynamically alter the styles of SVG elements. This led me to utilizing ViewChild and ElementRef. Here is an example from the HTML: <svg><g ...

How to Send TypeScript Object Excluding the '_id' Field?

I am currently developing a web app using Express, Mongoose, and Angular 2 (TypeScript). I want to post an instance of MyClass without including the _id field. In mongoose, the _id field is used for various operations in MongoDB. Here is how I have implem ...

Querying Cloud Firestore with User ID

I'm facing an issue with retrieving a subset of data based on the first letter of the name and including the UID of the document. No matter what I try, it just returns empty data. fetchDataByFirstLetter(firstLetter: string) { this.afs.collection(&a ...

Utilizing TypeDoc to Directly Reference External Library Documentation

I am working on a TypeScript project and using TypeDoc to create documentation. There is an external library in my project that already has its documentation. I want to automatically link the reader to the documentation of this external library without man ...

Error in creating object URL: `argument must be a Blob instance. Received an instance of Blob`

Within my express route, I have the following code snippet: let response = await fetch("http://someurl"); response = await response.blob(); console.log(response) const imgURL = URL.createObjectURL(response); However, I am encountering an error a ...

What is the method for including word boundaries in a regex constructor?

export enum TOKENS { CLASS = 1, METHOD, FUNCTION, CONSTRUCTOR, INT, BOOLEAN, CHAR, VOID, VAR, STATIC, FIELD, LET, DO, IF, ELSE, WHILE, RETURN, TRUE, FALSE, NULL, THIS } setTokenPatterns() { let tokenString: s ...

Can we securely retrieve nested properties from an object using an array of keys in TypeScript? Is there a method to accomplish this in a manner that is type-safe and easily combinable?

I wish to create a function that retrieves a value from an object using an array of property keys. Here's an example implementation: function getValue<O, K extends ObjKeys<O>>(obj: O, keys: K): ObjVal<O,K> { let out = obj; for (c ...

Ways to decrease the size of this item while maintaining its child components?

Here is an object that I am working with: { "name": "A", "children": [ { "name": "B", "open": false, "registry": true, "children": [ { ...

Can you explain the execution process of this Http.post method and provide details about the code path it follows

As I delve into the world of web development, one aspect that has me stumped is the functionality of the Http.post section within a project I stumbled upon on GitHub. Specifically, this pertains to an ExpressJS with Typescript repository I came across. So, ...