Adding a promise to an array using Javascript

I am facing an issue while attempting to create an array of promises and then calling them using Promise.all.

The problem lies in correctly pushing the functions into the array. It seems like they are getting executed instead of being inserted and waiting for Promise.all() to handle them.

function findSpecialAbility(players, gameId, message) {
  return new Promise(function(resolve, reject) {
    let playersWithSpecials = _.reject(players, function(p) {
      return p.role === 'alphaWolf' ||
        p.role === 'betaWolf' ||
        p.role === 'villager' ||
        p.role === 'alchemist' ||
        p.targetId === 0 ||
        p.abilityUsed === true;
    });
    if (playersWithSpecials.length === 0) {
      resolve();
    } else {
      let specialsToUse = [];
      for (let i = 0, j = playersWithSpecials.length; i < j; i++) {
        specialsToUse.push(useSpecialAbility(playersWithSpecials[i], gameId, message, players));
      }
      //Promise.all(specialsToUse).then(r = > console.log(r));
    }
  });
}


// Using promise below because some of the role will have database updates.
function useSpecialAbility(playerData, gameId, message, players) {
  return new Promise(function(resolve, reject) {
    if (playerData.role === 'seer') {
      let getTargetData = _.find(players, {
        id: playerData.targetId
      });
      message.guild.members.get(playerData.id).send(`Your target is a ${getTargetData.role}!`);
      resolve('foo');
    }
  });
}

Answer №1

There appears to be a misconception that they are being invoked instead of inserted and are waiting for Promise.all()

It seems like the intention is to have the code within the promises execute concurrently when Promise.all is called.

If that is the desired outcome, then enclosing the code in the promises may not be the best approach.


Instead, what needs to be done is wrapping the code intended for later execution in a simple function. These functions can then be added to an array and executed in sequence. Looking at the provided code, it's likely that promises might not even be necessary.

Refer to the example below:

// This function returns another function `runnable` which can be synchronously called later to obtain the result
function runLater (index) {
  return function runnable() {
    console.log(`this code will run later from ${index}`);
    return `from ${index}`;
  }
}

console.log('This runs now');

const tasks = [];

for (let i = 0; i < 3; i += 1) {
  tasks.push(runLater(i));
}

console.log('This runs second');


// Use Array.prototype.map to map the array of functions to their results by invoking each one.
const valuesOfTasks = tasks.map(task => task());
console.log({valuesOfTasks});

console.log('This runs last');


Promises are only needed when handling asynchronous control flow. Delaying execution can be achieved synchronously by encapsulating a section of code within a function. When you wish to run that code, simply invoke the function.

Edit:

I need all useSpecialAbility calls to finish before proceeding with my code. Some involve database read/write operations, hence the use of promises.

In this scenario, you would indeed have to utilize Promise.all. However, the promises must still be wrapped in functions without any arguments if simultaneous execution is desired.


The block of promise code actually executes synchronously (as opposed to running the block on .then or Promise.all invocation), so if postponing the execution of promises is still desired, simply enclose them in functions.

Consider the following example:

function waitThenSay(milliseconds, message) {
  return new Promise(resolve => {
    console.log(`waiting to say: "${message}"...`)
    setTimeout(() => {
      // Log to console for immediate effect
      console.log(message.toUpperCase() + '!');
      // Resolve with the message as well
      resolve(message);
    }, milliseconds);
  });
}

console.log('Runs first');

// Tasks is an array of functions returning promises
const tasks = [];
for (let i = 1; i <= 3; i += 1) {
  tasks.push(() => waitThenSay(i * 2000, `hello from task ${i}`));
}

console.log('Runs second');

// Execute the tasks by mapping each function to its invocation
const arrayOfPromises = tasks.map(task => task())

// Call Promise.all on that array
Promise.all(arrayOfPromises).then(result => {
  console.log({result});
});

Hope this clarifies things!

Answer №2

Here is a simple async/await method for adding promises to an array and using Promise.all on them afterward.

async (req, res, next) => {
    try{
        const promises = [];
        
        //Conditionally insert promises into the array

        if(req.user.hobby === "Hockey")
            promises.push(() => Hobby.find({name: "Hockey"}));

        else
            promises.push(() => Hobby.find({}));

        if(req.user.country === "Canada")
            promises.push(() => User.find({country: "Canada"}));
        
        //Execute the promises using Promise.all()            
                
        const docs = await Promise.all(promises.map(promise => promise()));
    
        if(docs.length === 0){
            var err = new Error('No documents found');
            err.status = 404;
            return next(err);
        }        

        if(docs[1])
            console.log(docs[1]); //array of User docs with country field value set to Canada
    
        console.log(docs[0]); //array of all hobbies or only hobbies with the name field set to Hockey

        res.json(docs);
    }
    catch(err){
        return next(err);
    }
}

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 there a method to give a webpage a subtle shimmering effect without utilizing CSS box-shadow?

Struggling to Develop a High-Performance Interface Feature I'm currently facing a challenge in coding an interface that requires a subtle and broad glow effect, similar to the example provided below: Exploration of Possible Solutions After expl ...

Synchronous: Establishing a connection to MongoDB once the server has successfully launched

I am curious to understand the interaction between Node.js asynchronous functions and MongoDB. If the server initializes before establishing a connection, and if my templates or Ajax requests rely on database data, will the serving of the HTML fail or will ...

Using data binding in VueJS to construct a dynamic URL

Exploring VueJS for the first time and it's been a great experience so far. However, I'm facing a couple of challenges with data binding. The requirement is for the customer to input an image URL, and no image should be displayed until a valid ...

The data retrieved from the web API is not undergoing the necessary conversion process

I am facing an issue with a web API call where the property checkNumber is defined as a double on the API side, but I need it to be treated as a string in my TypeScript model. Despite having the property defined as a string in my model, it is being receive ...

Neither the context nor props contain the element 'store' that you are searching for

Just stepping into the world of React can be overwhelming, but I'm determined to get my page to render properly: import React, { Component } from "react"; import { connect } from "react-redux"; import Header from '../components/Header'; imp ...

Utilizing for loop and specific string selectors in an undefined AJAX post request

Greetings fellow developers! I have been exploring jquery/ajax and here is what I've put together: $(function() { $("#moreAdd").click(function() { var dataString = []; var selector = '#repeat0'; var row; for(var i=0;$ ...

What is the best way to transform an Array into Json format using Java?

I'm in need of converting an Array into a Json Object, akin to this: String[] items = {"item1", "item2"}; The goal is to transform it into: { "items": ["item1", "item2"] } I am currently working with Spring (Jackson XML). This was my attempt: ...

React Three Fiber - THREE.BufferGeometry.computeBoundingSphere(): The calculated radius is invalid. It is possible that the "position" attribute contains NaN values causing this issue

Currently, I am working on a website using Reactjs and React Three Fiber for 3D components. Out of the total 3 3D components, 2 are functioning properly. However, one of them suddenly stopped working more than 6 hours ago, and I have been unable to find a ...

Navigating through Leaflet to reference a .json file

Looking to integrate a .json vector layer into a Leaflet.js map, which can be seen on the GitHub page here, with the source code available here. Here's a condensed version of the file for reference (full version visible on the linked GitHub page). & ...

Using the %d method, what is the best way to incorporate an array into a text string?

Being new to Python, I've learned that when you need to insert a variable into a text string, the common format to use is "Blah blah blah %d" % some_variable This will result in "Blah blah blah some_variable" I usually manage this fine, but I se ...

Creating an array by extracting form values in Angular

In my component, I have the following function: updateInfo(info: NgForm) { const changedValues = Object.keys(info.controls) .filter(key => info.controls[key].dirty === true) .map(key => { return { control: key, value: info.co ...

Steps to create a zigzagging line connecting two elements

Is it possible to create a wavy line connecting two elements in HTML while making them appear connected because of the line? I want it to look something like this: Take a look at the image here The HTML elements will be structured as follows: <style&g ...

Swapping values in JSON by comparing specific keys: A guide

I have JSON data that contains a key called reportData with an array of values: {"reportData":[ ["1185","R","4t","G","06","L","GT","04309","2546","2015","CF FE","01H1","20","23840","FF20"], ["1186","R","5t","R","01","L","TP","00110","1854","2016" ...

Handling and iterating through unfamiliar objects in AngularJS

I've been exploring the concept of generics in ASP.NET MVC for a while now, and it got me thinking about how generics are used in other languages like AngularJS. Let's say I have 2 endpoints to work with: www.listofstudents.com/all and www.list ...

Implementing an API call using Redux Saga within a React application

I have been diving into learning saga by following a tutorial on Medium and trying to implement it in StackBlitz. I encountered a path issue initially, managed to fix it after several attempts, but now a different problem has come up. Despite searching on ...

Tips for handling a disabled button feature in Python Selenium automation

When trying to click this button: <button id="btn-login-5" type="button" class="m-1 btn btn-warning" disabled="">Update</button> I need to remove the disable attribute to make the button clickable. This ...

Move your cursor over the image to activate the effect, then hover over it again to make the effect disappear

Looking to enhance my images with hover effects. Currently, all the images are in grayscale and I'd like to change that so that when you hover over an image, it reverts to full color and remains that way until hovered over again. I've noticed so ...

During the execution of a function, the React list remains empty which leads to the issue of having

Having difficulty preventing duplicate values because the item list is always empty when the function is called, even though I know it contains items. The function in question is AddToCart, being passed down to a child component named inventoryModal. The ...

Lightbox.options does not exist as a function within the lightbox plugin

I recently incorporated a lightbox plugin into my website, which can be found at the following link: For displaying items on the page, I am using markup similar to this example: <a href="images/image-2.jpg" data-lightbox="my-image">Image #2</a&g ...

Organizing dates with Javascript

Is there a way to convert a string from this format : 2014-06-12T23:00:00 To another format using JavaScript, like so : 12/06/2014 23:00 ...