我正在用NodeJS10和Mongoose5编写一个应用程序。我正在编写自定义服务器端分页功能。我想在控制器中运行分页,以分离关注点和可重用性。
我有一个查询以获取数据并在then()响应处理程序中将其返回。然后,我在then()处理函数中调用自定义分页功能。这行得通,但我担心“嵌套”的接/接模式。我认为这可能很麻烦,特别是如果返回响应之前需要对数据进行任何其他处理。
这是“嵌套”结构。我该如何改进它以使其不再嵌套且更具可读性,同时仍然捕获所有可能的错误并正确返回响应?请注意,这可以正常工作,只是设计模式比较混乱,如果可能的话,我想避免使用“嵌套”的then()语句。
router.get('/:id', (req, res, next) => {
const origin = 'routes/items.js GET /:id';
const id = req.params.id;
items.find({
_id: id
}).then(data => {
uiCtrl.pagination(data, req.query).then((result) => {
res.status(200).send(result);
}).catch((error) => {
console.error(`pagination failed ${error}`);
res.status(500).send(`pagination failed ${error}`);
});
}).catch((error) => {
console.log(`${origin} ${error}`);
res.status(404).send('Not found');
});
});
这是在上面的查询结果中调用的自定义异步函数。
const uiCtrl = {};
uiCtrl.pagination = async (data, query) => {
// pagination logic here
return data;
}
module.exports = uiCtrl;
答案 0 :(得分:1)
这里是使用普通async/await
东西的重写:
var data, results;
try {
data = await items.find({_id:id}).toArray();
}
catch (err) {
console.log(`${origin} ${error}`);
res.status(404).send('Not found');
}
try {
results = await uiCtrl.pagination(data, req.query);
}
catch (err) {
console.error(`pagination failed ${error}`);
res.status(500).send(`pagination failed ${error}`);
}
应该注意的是,鉴于我对您的代码一无所知,您可能还有其他一些事情可以使代码更易于阅读和使用(例如,拒绝承诺并对其做出有意义的事情,而不是抛出异常。您还需要将所有这些代码包装在async
方法中,以便可以使用await
关键字。
编辑
为了完整起见,现在给出完整的代码,我将以如下方式开始:
router.get('/:id', async (req, res, next) => {
const origin = 'routes/items.js GET /:id';
const id = req.params.id;
var itemResults, paginationResults;
try {
itemResults = await items.find({_id: id}).toArray();
}
catch (err) {
console.log(`${origin} ${error}`);
res.status(404).send('Not found');
}
try {
paginationResults = await uiCtrl.pagination(data, req.query);
res.status(200).send(result);
}
catch (err) {
console.error(`pagination failed ${error}`);
res.status(500).send(`pagination failed ${error}`);
}
});
作为一种优化或整理工作,我要做的另一件事是将捕获到的错误移到单个catch
块中,然后在那里解析错误,以使事情更简洁。
在讨论名为callback hell
的东西时也要包含此内容,这与您要查询的信息非常相关。
答案 1 :(得分:0)
这是根据接受的答案重新设计的解决方案。我收到此错误,我认为这是由于直接在路由器定义中放置了'async'关键字,例如(node:3564) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:3564) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
。也许是因为在这种格式下,它不是用then或catch处理的。
router.get('/', (req, res, next) => {
const origin = 'routes/items.js GET /';
async function queryWrapper() {
let data, results;
try {
data = await items.find();
console.log(`data ${data}`);
}
catch (err) {
console.log(`${origin} ${err}`);
}
try {
results = await uiCtrl.pagination(data, req.query);
}
catch (err) {
console.error(`pagination failed ${err}`);
}
if (results) {
return results;
} else {
return false;
}
}
queryWrapper().then((result) => {
res.status(200).send(result);
}).catch((error) => {
console.error(`${error}`);
res.status(500).send(`${error}`);
});
});
最后我得到了一个稍微修改的解决方案,我做了一个包装器函数,然后用then()处理函数调用了它。谢谢!
{{1}}