【问题标题】:run synchronouse function in a promise在 promise 中运行同步函数
【发布时间】:2019-10-11 23:51:56
【问题描述】:

我是 JS 和异步操作的新手。在使用 express 的 nodeJS 路由器中,我使用 mongoose 从 mongo 聚合了一些数据。数据是每隔 15 分钟从不同站点收集的天气数据。我使用猫鼬聚合管道处理数据,以获取每小时数据并按每个站点分组。但是数据需要进一步处理以获取例如相对湿度超过 90% 的时段,并为每个时段分配分数,因此我编写了一些针对每个站点(每个 geojson 对象)的同步函数。

猫鼬看起来像这样:

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;

}

现在我被困在如何在发布请求上通过猫鼬聚合管道返回的每个站点上应用这些函数:

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() 返回新的承诺

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

我希望看到所有网站都在 HTTP 响应输出中添加了新功能。但大多数时候,我得到 ReferenceError: error is not defined。

【问题讨论】:

    标签: javascript node.js express mongoose promise


    【解决方案1】:

    我想我已经明白了:

    1. 毕竟,必须通过将异步添加到这些函数来使所有同步函数异步;
    2. 在post router函数中重写这部分,特别是array map部分。我从this 阅读。并在map() 中尝试...catch...,否则它将无法正常工作。

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

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 2018-06-26
      • 1970-01-01
      • 2016-07-12
      • 1970-01-01
      • 1970-01-01
      • 2021-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多