0

I am currently writing in Node JS and am attempting to loop through a POST request based upon the number of results received from a Mongoose query. Below are the steps I am trying to accomplish, I'm currently stuck on the second task of this list.

  1. Query data from MongoDB
  2. For each object in result, take field and send it through POST request to API for additional data
  3. Combine Mongo data and data from API into one array and send new data back to Mongo.

The problem (I think) is around me trying to loop through the API a certain number of times. When I just console.log the result from the API, each object is there and looks correct. But when I try to include a console log of data from Mongo, I only get the last object (in this case the 3rd), instead of all 3. Here's my code below, can someone help me understand what I'm doing wrong?

module.exports.getRevenue = function() {
  //set date variables
  var dt = new Date();
  var thisYear = dt.getFullYear();      
  var thisMonth = dt.getMonth() + 1;
  var lastMonth = thisMonth - 1;
  if (lastMonth == 0) {
    thisYear = thisYear - 1;
    lastMonth = 12;
  }

//pull data for revenue 
Model.aggregate([

    //omitting query to make code smaller 

], function (err, result) {
    if (err) {
        console.log(err);
    } else {

        //clean up results in case tax settings are not present
        cleanResult = [];            
        for (i in result) {                              
            if (result[i]._id.userInfo.taxSettings) {
                cleanResult.push({
                    "id": result[i]._id.userId,
                    "pay": result[i].sum,
                    "status": result[i]._id.userInfo.taxSettings.status,
                    "exemptions": result[i]._id.userInfo.taxSettings.allowances
                })
            } else {
                cleanResult.push({
                    "id": result[i]._id.userId,
                    "pay": "1",
                    "status": "single",
                    "exemptions": "0"
                });
            }
        }           

        //attempt to pull tax info for each result and combine into 1 array
        finalTaxes = [];            
        for (i=0; i < cleanResult.length; i++) {

            temp = cleanResult[i];  

            request.post("https://taxee.io/api/v2/calculate/2020")   
            .set('Authorization', 'Bearer api_key_here')
            .set('Content-Type', 'application/x-www-form-urlencoded')
            .send({ state:"CA", year: thisYear, pay_rate: temp.pay, filing_status: temp.status, pay_periods: "12", exemptions: temp.exemptions }) 
            .then(result2 => {
                console.log(result2.body);
                console.log(temp[i]);

               //commenting out code which doesn't work. But this what I want to do.

                // finalTaxes.push({
                //         "userId": temp.id,
                //         "year": thisYear,
                //         "month": thisMonth,
                //         "revenue": temp.pay,
                //         "federal_tax": tempTax.per_pay_period.federal.amount,
                //         "state_tax": tempTax.per_pay_period.state.amount,
                //         "fica_tax": tempTax.per_pay_period.fica.amount,
                //     }); 

            })
            .catch(err => {
                console.log(err);
            })
        }                                                  
    }        
  })
};

Below is a sample output of the mongo query so you know what my data looks like

{id:'32464234325', pay:'1', status:'married', exemptions: '2'},
{id:'97463543252', pay:'4500', status:'single', exemptions: '0'},
{id:'98643253131', pay:'6000', status:'single', exemptions: '1'},
JonB
  • 29
  • 4
  • For coordinating between multiple `Promises`, I'd recommend using [`Bluebird.map`](http://bluebirdjs.com/docs/api/promise.map.html) or [`Promise.all`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all). https://stackoverflow.com/questions/11488014/asynchronous-process-inside-a-javascript-for-loop has notes about asynchronous operations kicked off in a for loop – klhr May 24 '20 at 19:56
  • Thank you! That link was very helpful. I am able to console.log each result, but I still can't push the results into an array (finalTaxes). Any idea how I can push all the results from the API into one array? – JonB May 24 '20 at 21:50

1 Answers1

0

As willis said, Promise.all can be used.
You can rewrite the code as below.

    const requestJobs = [];         
    for (i=0; i < cleanResult.length; i++) {

        temp = cleanResult[i];  

        requestJobs.push(request.post("https://taxee.io/api/v2/calculate/2020")   
        .set('Authorization', 'Bearer api_key_here')
        .set('Content-Type', 'application/x-www-form-urlencoded')
        .send({ state:"CA", year: thisYear, pay_rate: temp.pay, filing_status: temp.status, pay_periods: "12", exemptions: temp.exemptions }));
    }       

    Promise.all(requestJobs)
    .then(results => {
        const finalTaxes = results.map((result, index) => {
            return {
                userId : cleanResult[index].id,
                year : thisYear,
                month : thisMonth,
                revenu : cleanResult[index].pay,
                tax : result.x.y.z, // you can use result from post request
                ...
            }
        })
    })
    .catch(err => {
        console.log('some request failed');
    })
ryuken73
  • 763
  • 5
  • 13