0

My function uses promises, but it is not working correctly:

getShirtcolorsCount(){
    var params_red ;
    var red ;
    var params_blue ;
    var blue ;
    var numb = 0 ;
    var docClient = new DynamoDB.DocumentClient();

    // Query voor Shirts 
    params_red = {
        TableName: 'ShirtApp',
        IndexName: 'Shirt-index',
        KeyConditionExpression: 'ShirtC = :sbs AND ShirtQuantity >  :snr ' ,
        ExpressionAttributeValues: {
            ':sbs': 'Red' ,
            ':snr' : numb
        }
    };

    var redPromise = docClient.query(params_red).promise();
    redPromise.then(function(data){
        console.log('Success');  
        red = data.Count;
    }).catch(function(err) {
        console.log(err);
    });

    params_blue = {
        TableName: 'ShirtApp',
        IndexName: 'Shirt-index',
        KeyConditionExpression: 'ShirtC = :sbs AND ShirtQuantity >  :snr ' ,
        ExpressionAttributeValues: {
            ':sbs': 'Blue' ,
            ':snr' : numb
        }
    };

    var bluePromise = docClient.query(params_blue).promise();
    bluePromise.then(function(data){
        console.log('Success');  
        blue = data.Count ;      //NEED THAT to add to the array
    }).catch(function(err) {
        console.log(err);
    });

    var ShirtInfo = [{
        name: 'RedColor',
        value: red
    }, {
        name: 'BlueColor',
        value: blue
    }];

    // **** HERE I NEED HELP what should I PUT in the Promise.all for the array
    // I want redPromise and bluePromise to run at the same time after I receive 
    // data then add then to the array and return the array as the function
    Promise.all([redPromise, bluePromise]).then([ShirtInfo])

    return ShirtInfo;
}

As I added in comments, I want to run redPromise and BluePromise at the same time and after they received data from the web, add them to the array. And after that return that array. Almost everything works only the part where Promise.all is used. I can't figure out what to put after .then so the values would be added to the array:

Promise.all([redPromise, bluePromise]).then([])

And I can't figure out what to put to return the array using promise.

trincot
  • 317,000
  • 35
  • 244
  • 286
user3277530
  • 351
  • 6
  • 14

2 Answers2

0

I your case results from redPromise and bluePromise are written in function scope variable and can be pushed to array like this:

return new Promise(function (resolve, reject) {
  Promise.all([redPromise, bluePromise]).then(function () {
    ShirtInfo.push(red)
    ShirtInfo.push(blue)
    resolve(ShirtInfo)
  })
}

And where you call function that fetches this array you should also use

getShirtColorsCount().then(function(shirtInfo) {
  // Stuff
})

p.s. It will callback hell. May be better use babel and async-await or generator functions? It will be more readable

IC_
  • 1,624
  • 1
  • 23
  • 57
  • 1
    You should not provide code that uses the [Promise constructor anti-pattern](https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it). – trincot Aug 25 '17 at 01:50
  • @trincot i didn't know. I used this always – IC_ Aug 25 '17 at 01:53
  • @trincot also eslint:standard not mark that as antipattern – IC_ Aug 25 '17 at 01:55
0

Some issues:

  • You need to return the value of red and blue inside the then callback, otherwise those promises will resolve to undefined.
  • Likewise, you need to return the return value of Promise.all
  • You cannot acccess red and blue synchronously, as those will still be undefined. So that must happen within a then callback.

I would also avoid the code duplication you have, and work with a list of colors you are interested in, and then cycle through those:

getShirtcolorsCount(){
    var params;
    var colors;
    var promises;
    var numb = 0;
    var docClient = new DynamoDB.DocumentClient();

    colors = ['Red', 'Blue']; // <--- make code generic
    promises = colors.map(function (color) {
        // Query voor Shirts 
        var param = {
            TableName: 'ShirtApp',
            IndexName: 'Shirt-index',
            KeyConditionExpression: 'ShirtC = :sbs AND ShirtQuantity > :snr ',
            ExpressionAttributeValues: {
                ':sbs': color, // <-- make it dynamic to avoid code duplication
                ':snr' : numb
            }
        };
        return docClient.query(params_red).promise();
    });

    // Make sure to return the promise    
    return Promise.all(promises).then(function (responses) {
        console.log('Success');  
        var shirtInfo = responses.map(function (data, i) {
            return {
                name: color[i] + 'Color',
                value: data.Count
            };
        });
        return shirtInfo;
    }).catch(function(err) {
        console.log(err);
    });
}

Once you work with promises, you must use the results as promises too. You cannot expect a function to return the value synchronously. So when you call getShirtcolorsCount, use then to access the result:

getShirtcolorsCount().then(function (shirtInfo) {
    console.log(shirtInfo);
});
trincot
  • 317,000
  • 35
  • 244
  • 286
  • I got error on this part of the code value: data.Count the the erorr is [ts] Property 'Count' does not exist on type '{}'. any. If I remove the .Count it works but I dont need all the whole object only the Count property – user3277530 Aug 26 '17 at 00:34
  • I got error but fixed it return Promise.all(promises).then(function (responses) { } need to be ---> (responses: any) – user3277530 Aug 26 '17 at 07:37
  • OK, that was a TypeScript error. My answer is in plain JavaScript. But indeed with `: any` you circumvent that TypeScript complains. – trincot Aug 26 '17 at 07:51
  • since I am using it in angular I needed to add the return of shirtInfo to a var tingle in a component so I did this and it worked this.ddb.getShirtcolorsCount().then(shirtInfo => this.tingle = shirtInfo); I thx again for all your help – user3277530 Aug 27 '17 at 18:27