最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

node.js - JavaScript Promises - Creating an array of promises to be executed together - Stack Overflow

programmeradmin3浏览0评论

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);

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);

Share Improve this question edited Jan 17, 2017 at 23:21 Jim from Princeton asked Jan 17, 2017 at 22:49 Jim from PrincetonJim from Princeton 7411 gold badge9 silver badges22 bronze badges 8
  • 1 unrelated, but you should use myPromises = capturedData.map(...) instead of a .forEach / .push loop – Alnitak Commented Jan 17, 2017 at 22:53
  • @Alnitak,coming from C++ it's hard for me to shed the for-loop paradigm! I suppose you offer that up due to the blocking nature of .forEach... or some other reason? – Jim from Princeton Commented Jan 17, 2017 at 23:17
  • .forEach has no "blocking nature" ... the .map pattern is just more efficient ... Promise.all(capturedData.map(function(value) { ... return(new Promise ... - no need for the myPromises var at all – Jaromanda X Commented Jan 17, 2017 at 23:33
  • @JimfromPrinceton no, it's simpler than that - if you've got an array as input, and want an equal sized array as output (with a 1:1 mapping between input elements and output elements) then .map is simply the right function for the job. – Alnitak Commented Jan 18, 2017 at 7:16
  • @Alnitak Is it deemed fine to use map/filter if the Promises have side-effects (eg. POST/PATCH/etc)? – Winston Guess Commented Nov 20, 2024 at 9:50
 |  Show 3 more comments

2 Answers 2

Reset to default 12

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);
    });

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

发布评论

评论列表(0)

  1. 暂无评论