Ways to generate a collection of promises using array.reduce?

I'm currently working on refactoring an array.map function that iterates over an array and returns an array of promises. The task at hand is to switch from using .map to .reduce. However, after implementing .reduce without altering the business logic, I noticed a significant increase in processing time due to asynchronous calls being made for each element in the array.

Is there a way to utilize reduce to generate an array of promises that can be resolved efficiently using Promise.all() later on?

In an attempt to address this issue, I have conducted some experiments and included a snippet below showcasing the solutions I have tried along with the desired outcome.

If anyone could demonstrate how to achieve this, it would be greatly appreciated.

interface IUser { name: string; balance: number | undefined; }

let user1 = { name: 'user1', balance: undefined }
let user2 = { name: 'user2', balance: undefined }
let user3 = { name: 'user3', balance: undefined }
const users = [user1, user2, user3]

async function calculateBalance(user: IUser): Promise<IUser> {
  await new Promise((resolve) => setTimeout(resolve, 5000));
  user.balance = Math.floor(Math.random() * 5000) + 1000;

  return user;
}

async function processUsers() {
  return users.reduce(async (acc, currUser, index) => {
    return [ ...acc, calculateBalance(currUser) ] // not working
    return acc.push(calculateBalance(currUser)) // Argument of type 'Promise<IUser>' is not assignable to parameter of type 'never'
    return acc.concat(calculateBalance(currUser)) // Same above
  }, [])
}

const processedUsersArray = await processUsers();
await Promise.all(processedUsersArray) // Desired thing for the sake of performance

Answer №1

When it comes to the scenario you've presented, using a .map function works perfectly fine

interface IUser {
  name: string;
  balance: number | undefined;
}
const user1 = { name: 'user1', balance: undefined };
const user2 = { name: 'user2', balance: undefined };
const user3 = { name: 'user3', balance: undefined };
const users = [user1, user2, user3];
const init = async () => {
  async function calculateBalance(user: IUser): Promise<IUser> {
    await new Promise((resolve) => setTimeout(resolve, 5000));
    user.balance = Math.floor(Math.random() * 5000) + 1000;

    return user;
  }

  async function processUsers() {
    const promises = users.map((user) => calculateBalance(user));
    const processedUsersArray = await Promise.all(promises);
    return processedUsersArray;
  }

  const processedUsersArray = await processUsers();
  console.log(processedUsersArray);
};

init();

If there's a need for using reduce, you can achieve that in this way

const promises = users.reduce((acc, user) => {
  acc.push(calculateBalance(user));
  return acc;
}, [] as unknown as Promise<IUser>[]);

Answer №2

By using the push() method, you can easily add new elements to the end of an array and retrieve the updated length of the array.

It seems like in your reduce function, you are mistakenly trying to push a number, which is not the correct approach.

To handle this scenario correctly, it is recommended to utilize map() instead of reduce and avoid mixing await with promises.

const user1 = { name: 'user1', balance: undefined }
const user2 = { name: 'user2', balance: undefined }
const user3 = { name: 'user3', balance: undefined }

const users = [user1, user2, user3]

function calculateBalance(user) {
  return new Promise((resolve) => {
    setTimeout(() => {
      user.balance = Math.floor(Math.random() * 5000) + 1000;
      resolve(user);
    }, 1000)
  });
}

function processUsers(users) {
  return users.map(currUser => calculateBalance(currUser));
}

(async () => {
  const results = await Promise.all(processUsers(users));
  console.log(results);
})();

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

Is it possible to trigger the JavaScript mouseover function following a click event?

Is it possible to call a function on mouse over after the first click event is triggered by the user? <a href="javascript:void(0);" id="digit<?php echo $k;?>" onClick="javascript:return swapClass('<?php echo strtoupper($v);?>',&ap ...

Could not locate the express.js file

Currently in the process of learning express/node.js, but struggling to locate the page at localhost:3000/info You can view screenshots of my code below ...

Storing a large 79MB file in couchDB resulted in a memory overload

Storing files in couchDB requires the use of a byte array. ByteArrayOutputStream out = new ByteArrayOutputStream((int) file.length()); Unfortunately, an exception was thrown during this process. Exception in thread "main" java.lang.OutOfMemoryError: J ...

Setting up lint-staged for Vue projects: A step-by-step guide

After setting up a new Vue3 app using the Vue CLI and configuring Prettier as my linter, I decided to implement commitlint, husky, and lint-staged for validating commit messages and linting the code before pushing it. My Approach Following the instructio ...

Transform the Asp.net JavaScript jsgantt-improved Gantt chart to be compatible with Blazor

Struggling to implement a Gantt chart in Blazor with razor pages after finding a nice one for Asp.net. Any tips on how to proceed? I've already added jsgantt.js and jsgantt.css to wwwroot and included references in index.html. But now, how do I go a ...

Can elements be prevented from resizing in relation to another element without using position:absolute?

Is there a way to prevent elements in a <div> from moving when an adjacent element is resized, without using position:absolute? Any help would be greatly appreciated. Thank you in advance! ...

Troubleshooting a problem with AJAX returning the data

Currently, I have a javascript function that calls another javascript function called zConvertEmplidtoRowid. This second function utilizes an ajax call to execute a query and retrieve data stored in a variable named rowid. My challenge lies in figuring out ...

Is there a way to duplicate the method signature and apply it to a different method?

I came across a library that contains the following class: class Dog { public run(speed: number, movement: number): void; public run(speed: number, type: string): void; public run(speed: number, opts: string | number): void { // performing some a ...

Tips for refreshing an angularjs $scope using $.get jquery

Attempting to implement the code below using $scope: var scopes = "https://www.googleapis.com/auth/contacts.readonly"; setTimeout(authorize(), 20); function authorize() { gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, h ...

Is there a way to use CSS to generate a disappearing triangle-shaped div that will only vanish when clicked directly on the triangle and not when clicked on the surrounding overflow area?

In a different discussion, it was mentioned that the method used to create a CSS triangle allows for triggering the hover state or click event only when the cursor is inside the triangle. There is a demo provided to demonstrate this with the hover state. ...

Preflight response indicates that the Access-Control-Allow-Methods does not permit the use of the PATCH method

Implementing the axios PATCH method in my ReactJS project to update a record is resulting in a failure with the following error message: Failed to load : Method PATCH is not allowed by Access-Control-Allow-Methods in preflight response. Below is the co ...

Encountering an Error with "Access-Control-Allow-Origin" Request While Trying to Access the API

I'm currently facing an issue with fetching data from the Rescue Time API. My request is made in a JavaScript file using the jQuery get() method. Below is the snippet of JavaScript code related to the API GET request: $.get('https://www.rescueti ...

A guide on incorporating dynamic information into JSON files with PHP

I am currently working on developing a checkbox tree where I require dynamic values for checkboxes. Below is my code snippet. Initially, I have static data in JSON format and now I need to retrieve dynamic data from a MySQL database. Despite trying vario ...

Extracting live content from a website within a native Webview

Running an eCommerce website along with a simple mobile app for both iOS and Android that features a basic tab bar menu, including icons like a shopping cart, profile, refresh button, etc., as well as a Webview to display the website content. The App' ...

Error: Authorization requires both data and salt arguments

As a novice in NodeJS, I attempted to create an authentication form using NodeJS + express. The issue I am facing is regarding password validation - specifically, when "confirmpassword" does not match "password", it should return nothing. Despite my effo ...

Creating a RESTful API

To begin with, I am a newcomer to web frameworks and we are currently using Meteor. In our database, we have a collection of Students: Students = new Mongo.Collection('students'); At the moment, we have defined a Rest API as follows: // Maps t ...

Trigger a class method in an event using Angular with Typescript

I am completely new to TypeScript and Angular, and I am attempting to create a basic drawing component on a canvas. However, I have reached a point where I feel lost and confused about my code. The concept of "this" in TypeScript has been a major stumbling ...

Using Ajax and JQuery to show a success message prominently

Currently, I have a fully functional flash system implemented in PHP to display a success message to the user once an entry is created in the database. In one of the forms on my website, there is a select field where users should be able to seamlessly add ...

Populating the DOM with a mix of strings and HTMLDivElements by iterating through an array using *ngFor

I have a specific layout requirement that needs to resemble this example: https://i.sstatic.net/4kP2q.png The desired layout should utilize CSS properties like display: grid; someFunction(data) { this.data = data; ...

Navigating CSS imports when implementing server-side rendering in React

This situation is somewhat similar to another question about Importing CSS files in Isomorphic React Components However, the solution proposed involves a conditional statement that checks if the import is being done from the server or the browser. The iss ...