我需要为同一请求class
获取两个不同的MongoDB集合(Deque<Action> undoStack = new ArrayDeque<>();
Deque<Action> redoStack = new ArrayDeque<>();
public void doAction(Action action) {
redoStack.clear(); // new action prevents redo of previous undo
undoStack.push(action);
}
public Action undoAction() {
Action action = undoStack.pop(); // Throws exception if stack is empty
redoStack.push(action);
return action;
}
public Action redoAction() {
Action action = redoStack.pop(); // Throws exception if stack is empty
undoStack.push(action);
return action;
}
和db.stats
)。
现在,在下面的代码中,我将查询嵌套在回调函数中。
db.tables
此代码有效,但有些事情似乎不对。所以我的问题是:
如何避免这种嵌套结构?因为它不仅看起来很丑,而且在处理这些请求时,客户端没有响应,这很糟糕。
答案 0 :(得分:2)
您现在拥有的内容在JavaScript中被称为回调地狱。这是Promises
派上用场的地方。
以下是您可以做的事情:
router.post('/', (req, res) => {
let season = String(req.body.year);
var queries = [
db.stats.findOne({ Year: season }),
db.tables.findOne({ Year: season })
];
Promise.all(queries)
.then(results => {
if (!results[0]) {
console.log("Error in Stats");
return; // bad response. a better way is to return status 500 here
} else if (!results[1]) {
console.log("Error in Tables");
return; // bad response. a better way is to return status 500 here
}
let resultData = getResult(results[0]);
let resultTable = getTable(results[1]);
res.render('index.html', { data: {
result : resultData,
message: "Working"
} });
})
.catch(err => {
console.log("Error in getting queries", err);
// bad response. a better way is to return status 500 here
});
});
看起来您正在使用Mongoose作为您的ODM来访问您的mongo数据库。如果您未将函数作为第二个参数传入,则函数调用返回的值(例如db.stats.findOne({ Year: season })
)将是Promise。我们将所有这些未解决的Promise放在一个数组中,并调用Promise.all
来解决它们。通过使用Promise.all
,您将等待所有数据库查询执行,然后再继续呈现index.html
视图。在这种情况下,数据库函数调用的结果将按results
数组的顺序存储在queries
数组中。
此外,除了res.status(500).send("A descriptive error message here")
来电之外,每当服务器端出现错误时,我建议您执行console.log
之类的操作。
以上将解决您的嵌套结构问题,但后一个问题仍然存在(即客户端在处理这些请求时没有响应)。为了解决这个问题,您需要首先确定您的瓶颈。什么函数调用占用了大部分时间?由于您使用的是findOne
,因此除非您的服务器与数据库之间的连接存在延迟问题,否则我认为这不会成为瓶颈。
我将假设POST
请求不是通过AJAX完成的,因为你有res.render
,所以这个问题不应该由任何客户端代码引起。我怀疑getResult
或getTable
(或两者)中的任何一个占用了相当多的时间,考虑到它会导致客户端无响应。查询数据库时数据的大小是多少?如果它的大小太大而需要花费大量的时间来处理,我建议改变请求的方式。您可以在前端使用AJAX向后端发出POST请求,然后将该响应作为JSON对象返回。这样,浏览器上的页面就不需要重新加载,您将获得更好的用户体验。
答案 1 :(得分:1)
router.post('/', async(req, res) => {
let season = String(req.body.year);
let resultData, resultTable;
try {
const [data1,data2] = await Promise.all([
db.stats.findOne({Year: season}),
db.tables.findOne({Year: season})
]);
if (data1 && data2) {
resultData = getResult(data1);
resultTable = getTable(data2);
return res.render('index.html', {
data: {
result: resultData,
message: "Working"
}
});
}
res.send('error');
console.log("Error");
} catch (err) {
res.send('error');
console.log("Error");
}
});
&#13;