Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

run synchronouse function in a promise

I am new to JS and async operations. In a router of nodeJS using express, I have aggregated some data from mongo using mongoose. The data is weather data collected from different sites every 15 minutes interval. I processed the data with mongoose aggregate pipeline to get hourly data and group by each site. But the data needs a further process to get periods where for example relative humidity over 90% and assign scores to each period so I wrote some synchronous functions that target each site (each geojson object).

Mongoose looks something like that:

module.exports.filteredData = function (collection, dateInput) {
return collection.aggregate([

    {
        $addFields :{
            DateObj: {
                $dateFromString: {
                    dateString: "$DateTime",
                    format: '%Y-%m-%d'
                }
            },
        }
    },

    {
        $addFields :{
            NewDateTimes: {
                $dateFromParts:{
                    'year': {$year: '$DateObj'},
                    'month':{$month: '$DateObj'},
                    'day':{$dayOfMonth: '$DateObj'},
                    'hour': {$toInt: "$Time"}
                }
            }
        }
    }

...

synchronouse functions:

const calcDSV = function(featuresJSON){

    // featuresJSON  
    const SVscore = [];
    const tuEval = featuresJSON.features.properties.TU90; // array
    const obArr = featuresJSON.features.properties.OB; // array
    const periodObj =  getPeriods(tuEval);// get period position
    const paramObj =  getParams(periodObj, obArr); // get parameters
    const periodDate =   getPeriodDate(featuresJSON, periodObj);
    const removeTime =  periodDate.beginDate.map(x=>x.split('T')[0]);


    let hourly = paramObj.hourCounts;
    let avgTemps = paramObj.avgTemps;


    for(let i = 0;i<hourly.length; i++){

        let score =  assignScore(avgTemps[i], hourly[i]);
        SVscore.push(score);

    }

    // output sv score for date


    const aggreScore =  accumScore(removeTime, SVscore);


    aggreScore.DSVdate = aggreScore.Date.map(x=>new Date(x));


    featuresJSON.features.properties.periodSV = SVscore;
    featuresJSON.features.properties.Periods = periodDate;
    featuresJSON.features.properties.DSVscore = aggreScore;

    return  featuresJSON;

}

Now I am stuck on how to apply those function on each site return by the mongoose aggregate pipeline on a post request:

router.post('/form1', (req, res, next)=>{

const emdate = new Date(req.body.emdate);
const address = req.body.address;
const stationDataCursor = stationData.filteredData(instantData, emdate);

stationDataCursor.toArray((err, result)=>{
    if(err){
        res.status(400).send("An error occurred in Data aggregation")
    };


    res.json(result.map(x=>calcDSV.calcDSV(x)));


})


});

I tried in the callback:

stationDataCursor.toArray((err, result)=>{
    if(err){
        res.status(400).send("An error occurred in Data aggregation")
    };


    res.json(result.map(async (x)=>await calcDSV.calcDSV(x))));


})

and using then():

stationDataCursor.toArray().then((docArr)=>{

    let newfeature = await docArr.map(async (x)=> await calcDSV.calcDSV(x))));


    res.json(newfeature);

})

or make calcDSV() returns new promise

    return  new Promise((rej, res)=>{
            resolve(featuresJSON);
     })

I would expect to see all sites with a new feature added in the HTTP response output. But most of the time, I got ReferenceError: error is not defined.

like image 299
Xp.L Avatar asked May 28 '26 15:05

Xp.L


1 Answers

I think I have figured it out:

  1. after all, have to make all synchronous functions asynchronous by prepending async to those functions;
  2. rewrite this part in the post router function, especially the array map part. I read from this. and in the map() gonna have try...catch... in it, otherwise it won't work.

    await stationDataCursor.toArray().then(async (docArr)=>{
    
            const newfeature = await Promise.all(docArr.map(async function(x){
                try{
                    const feature = await calcDSV.calcDSV(x);
    
                    return feature
                } catch(err){
                    console.log("Error happened!!! ", err);
    
                }
    
            }));
    
            res.json(newfeature)
    
    })
    

Hope it helps.

like image 155
Xp.L Avatar answered May 30 '26 04:05

Xp.L