Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript Promises - Creating an array of promises to be executed together

I'm working with Node.js on async calls to noSQL DynamoDB. I first query to see which 'buddy list(s)' the account belongs. That may return from zero to 'n' new Primary Keys that will contain lists of all of the members of each of those buddy lists. Think of them as clubs to which a person belongs... you may have none or many; each club has several members or even one.

So far (and I am working with Promises for the first time here... though I have used callbacks on prior JA projects) I'm OK with where I am, but I know that I am assembling the array of promises incorrectly. That is, I can see in the console that the .then function executes before both promises resolve. For the record, I do expect that... it seems reasonable that any .then may be satisfied with a single promise resolving.

Anyways, Can someone offer up some tips as to how to structure? I'd like to end up with pseudo:

getBuddyLists .then(getAllTheBuddiesInTheLists) .then(function(){//doSomething});

my Node.js code:

const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({region:'us-east-1'});
var buddyGroups = [];

exports.handler = function(event, context, callback) {
    var params = {
        TableName: 'USER_INFORMATION',
        Key: {
            "DEVICE_ID": event.DEVICE_ID
        }
    };

    var getBuddyList = new Promise(function(resolve, reject){
        docClient.get(params, function(err, data){
            if(err){
                reject(err);
            }
            else{
                var dataJSON = JSON.parse(JSON.stringify(data));
                dataJSON.Item.my_buddies.values.forEach(function(value){
                    buddyGroups.push(value);
                });
                console.log('Got buddy groups: ' + buddyGroups);
                resolve(buddyGroups);
            }
        });
    });

    getBuddyList.then(function(capturedData){  // capturedData => an array of primary keys in another noSQL document
        console.log('groups: ' + capturedData);
        var myPromises = [];
        capturedData.forEach(function(value){
            var reqParams = {
                        TableName: "buddy_list",
                        Key: {"BUDDY_ID": value}
                    };
            myPromises.push(new Promise (function(resolve, reject){
                docClient.get(reqParams, function(err, data){
                    if(err){
                        //console.log(err, data);
                    reject(err);
                    }else{
                        var returnedJSON = JSON.parse(JSON.stringify(data));
                        console.log(returnedJSON);
                        resolve(returnedJSON);
                    }
                });
            }));
        });
        //
        Promise.all(myPromises); // ADDED IN EDIT <<<<<<<<<<<<<<<<<<<<<<
        // how to make sure all of myPromises are resolved?
        //
    }).then(function(){
            console.log("done");
        })
    .catch(function(err){
        console.log("error message:" + error);
    });
};

EDIT: Added location of Promise.all(myPromises);

like image 899
Jim from Princeton Avatar asked Jan 17 '17 22:01

Jim from Princeton


People also ask

How do you run multiple Promises together?

In this approach, we will use Promise. all() method which takes all promises in a single array as its input. As a result, this method executes all the promises in itself and returns a new single promise in which the values of all the other promises are combined together.

Can we chain Promises in JavaScript?

JavaScript Promise Chaining Promises are useful when you have to handle more than one asynchronous task, one after another. For that, we use promise chaining. You can perform an operation after a promise is resolved using methods then() , catch() and finally() .

Does promise all run Promises in parallel?

As you can see, Promise. all executes code concurrently, but what is parallel execution? JavaScript is single-threaded and can only perform a single chunk of work at a time, so parallel execution is not possible with JavaScript, except for some circumstances such as web workers.


2 Answers

Just to clarify how you would use Promise.all, even though you accepted an answer, you edited the question, but still are not using it correctly

Also, the discussion of .map vs .forEach - this is how you would use .map

    getBuddyList.then(function(capturedData){  // capturedData => an array of primary keys in another noSQL document
        console.log('groups: ' + capturedData);
        // changes to use .map rather than .forEach
        // also, you need to RETURN a promise - your edited code did not
        return Promise.all(capturedData.map(function(value){
            return new Promise (function(resolve, reject){
                var reqParams = {
                    TableName: "buddy_list",
                    Key: {"BUDDY_ID": value}
                };
                docClient.get(reqParams, function(err, data){
                    if(err){
                        //console.log(err, data);
                    reject(err);
                    }else{
                        var returnedJSON = JSON.parse(JSON.stringify(data));
                        console.log(returnedJSON);
                        resolve(returnedJSON);
                    }
                });
            });
        }));
    }).then(function(){
            console.log("done");
        })
    .catch(function(err){
        console.log("error message:" + error);
    });
like image 60
Jaromanda X Avatar answered Nov 07 '22 14:11

Jaromanda X


You're looking for Promise.all(myPromises), which returns a single promise of an array of the results of the promises.

like image 29
SLaks Avatar answered Nov 07 '22 16:11

SLaks