我正在对路由(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对象返回?
答案 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
放置数据的地方。