在promise中运行同步功能 [英] run synchronouse function in a promise
问题描述
我是JS和异步操作的新手.在使用express的nodeJS路由器中,我使用mongoose从mongo聚合了一些数据.数据是每15分钟间隔从不同站点收集的天气数据.我使用猫鼬聚合管道处理了数据,以获取每小时数据并按每个站点进行分组.但是数据需要进一步的处理,以获取相对湿度超过90%的时间段,并为每个时间段分配得分,因此我编写了针对每个站点(每个geojson对象)的一些同步函数.
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).
猫鼬看起来像这样:
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"}
}
}
}
}
...
同步功能:
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)));
})
});
我在回调中尝试过
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))));
})
并使用then():
stationDataCursor.toArray().then((docArr)=>{
let newfeature = await docArr.map(async (x)=> await calcDSV.calcDSV(x))));
res.json(newfeature);
})
或使calcDSV()返回新的诺言
or make calcDSV() returns new promise
return new Promise((rej, res)=>{
resolve(featuresJSON);
})
我希望看到所有在HTTP响应输出中添加了新功能的网站.但是大多数时候,我遇到了ReferenceError:错误未定义.
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.
推荐答案
我想我已经知道了:
- 毕竟,必须通过在所有同步功能之前添加异步功能来使其异步;
-
在后路由器功能中重写此部分,尤其是数组映射部分.我从此一个>.并在
map()
中尝试... catch ...在其中,否则它将无法正常工作.
- after all, have to make all synchronous functions asynchronous by prepending async to those functions;
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)
})
希望有帮助.
这篇关于在promise中运行同步功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!