在Mongoose中使用Promise链式调用是否正确?求该路由的更优写法
优化Mongoose查询的Promise写法,摆脱嵌套困扰
嘿,很高兴你开始尝试用Promise解决回调地狱的问题!你当前的代码确实能正常运行,但嵌套的.then()写法本质上还是“回调嵌套”的变体,并没有完全发挥Promise的优势。这里有两种更优雅的写法,帮你把代码变得更清爽:
方法一:用Promise.all()并行处理无依赖查询
注意到Department.find({})和Employee.findById(req.user.employee.id)这两个查询是互不依赖的(不需要先用其中一个的结果去查另一个),所以完全可以并行执行,这样还能提升接口的响应速度。
改写后的代码:
router.get('/homehr/employees/new', middleware.isLoggedInAsHR, (req, res) => { // 把两个独立的Promise放在数组里,用Promise.all并行执行 Promise.all([ Department.find({}), // Mongoose查询本身就是Promise,可省略.exec() Employee.findById(req.user.employee.id) ]) .then(([allDepartments, foundEmployee]) => { // 解构数组拿到两个查询的结果 res.render('hr/employees/new', { departments: allDepartments, employee: foundEmployee, blogs: allBlogs }); }) .catch((err) => { console.log(err); req.flash('error', err.message); return res.redirect('back'); }); });
这样就把嵌套的.then()变成了扁平的结构,而且两个查询同时执行,效率更高。
方法二:用async/await(推荐!)
async/await是ES2017引入的语法,它让异步代码看起来像同步代码,可读性拉满,现在已经是处理异步操作的主流方式。
改写后的代码:
router.get('/homehr/employees/new', middleware.isLoggedInAsHR, async (req, res) => { try { // 用await等待每个Promise完成,拿到结果 const allDepartments = await Department.find({}); const foundEmployee = await Employee.findById(req.user.employee.id); // 直接渲染页面,逻辑和同步代码完全一致 res.render('hr/employees/new', { departments: allDepartments, employee: foundEmployee, blogs: allBlogs }); } catch (err) { console.log(err); req.flash('error', err.message); return res.redirect('back'); } });
这种写法几乎消除了所有嵌套,逻辑一目了然,出错时直接用try/catch捕获,和同步代码的错误处理方式一致,非常容易维护。
补充小提示
Mongoose的查询方法(比如find()、findById())本身就返回Promise,所以你可以直接用.then()或者await,不一定需要加.exec()——不过如果是在一些老版本的Mongoose里,或者需要更严格的Promise规范时,.exec()也可以保留,不影响功能。
内容的提问来源于stack exchange,提问作者Kassaï-迈克-Kaym
相关产品推荐
相关产品推荐

