来自单个路由的节点和多个函数调用,返回计算数据?

时间:2018-03-19 16:29:11

标签: node.js mongodb typescript express mean-stack

我正在对路由(MEAN堆栈)进行单个API调用,以在前端填充chart.js图。 API调用需要返回年初至今,月初至今和历史数据(去年的年初至今,去年的月初至今等)。我试图遵循的功能性编程最佳实践正在使它变得一团糟;有更好的方法吗?

这是我到目前为止填写的模板:

router.post('/sales_chart', (req, res, next)=>{
    const store = req.body.store;
    const date = req.body.date;

    dailySalesModel.getSalesYTD (store, date, (err, daily_data)=>{
        if(err) logger.error(err);
        if(!daily_data) {
            return res.json({success: false, message: 'No daily sales data found'});
        }
        let sales = [];
        // **calculate sales year-to-date**

        // Fetch the same data from one year earlier.
        dailySalesModel.getSales (store, SAME_DAY_LAST_YEAR, (err, last_year_daily_data)=>{
            if(err) throw err;
            if(!last_year_daily_data) {
                return res.json({success: false, message: 'No last year daily sales data found'});
            }

            let last_year_sales = [];
            // **calculate sales year-to-date**

            dailySalesModel.getSalesMTD (store, date, (err, mtd_data) => {
                if(err) logger.error(err);
                if(!mtd_data) {
                    return res.json({success: false, message: 'No MTD sales data found'});
                }
                let mtd_sales = [];
                // **calculate sales month-to-date**

                // Fetch the same data from one year earlier.
                dailySalesModel.getSalesMTD(store, SAME_DAY_LAST_YEAR, (err, last_year_mtd_data) => {
                    if(err) logger.error(err);
                    if(!last_year_mtd_data) {
                        return res.json({success: false, message: 'No last year MTD sales data found'});
                    }
                    let last_year_mtd_sales = [];
                    // **calculate sales month-to-date**

                    // and so on... 
                    dailySalesModel.getEvenMoreHistoricalData(...)
                        ...


                })
            });

            return res.json({success: true, sales_data: { sales: sales, 
                                                          last_year_sales: last_year_sales, 
                                                          mtd_sales: mtd_sales, 
                                                          last_year_mtd_sales, mtd_last_year_sales, 
                                                          date: date } });
        });
    })
});

...我开始觉得所有的“嵌套”#39;功能不是必需的,必须有更好的方法来做到这一点。例如,我不认为这会处理某些函数调用返回null或空数据的情况(可能是新商店去年在指定日期没有打开)但我想继续获取其余的返回的数据。

有没有更好的方法进行多次调用并将所有计算的数据作为单个JSON对象返回?

1 个答案:

答案 0 :(得分:0)

你能把你的dailySalesModel方法写成承诺吗?那会让你免于回调地狱。

您可以做的另一件事是将每个这些分成middlware。 express中的中间件只是在发出请求和发送响应之间运行的函数。因此,例如,您可能有一个middlewares.js文件:

function getSalesYTD(req, res, next) {
  const { store, date } = req.body
  dailySalesModel.getSalesYTD(store, date, (err, result) => {
    if (err) return next(err)
    res.locals.daily_data = result
    next()
  })
}

function getSales(req, res, next) {
  // etc
  // access daily_data on res.locals.daily_data
}

(如果您之前没有遇到res.locals,它只是响应对象上的一个属性,您可以在一个请求/响应周期中存储内容。它在周期的持续时间内为每个新请求清除。)

然后在你的路线中,将它们连在一起:

const { getSalesYTD, getSales, otherThings } = require('./middlewares')
router.post('/sales_chart', getSalesYTD, getSales, otherThings, (req, res) => {
  res.json({
    daily_data: res.locals.daily_data
    // etc
  })
})

这是你希望完成的事情吗?

这样做的另一个好处是,如果您需要在不同的路径中创建其中一个请求,则不必再将其写出来 - 只要您记得,就可以使用相同的中间件你在res.locals放置数据的地方。

Here's an example of a route that uses this pattern.