使用Promise优化MongoDB请求的技术疑问及代码改进咨询
关于Promise与Mongoose的两个问题解答
嘿,很高兴看到你在学习Promise和Mongoose——这俩可是Node.js后端开发的核心工具!咱们来逐个拆解你的问题:
问题1:在Promise内部使用回调函数是否正确?
这种做法是正确的,本质上就是把传统的回调式API转换成Promise风格的写法,这是处理旧版回调接口的标准手段之一。不过你的代码里有个小陷阱得注意:
看你写的itemQuery部分:
var itemQuery = new Promise(function(resolve, reject){ Items.find({}, function(err, allItems){ if (err) { console.log("error 3"); reject("error 4");} else { resolve(allItems); reject("error 5"); } }); });
在else块里,你先调用了resolve(allItems),紧接着又调用了reject("error 5")。但Promise的状态是不可逆的——一旦调用了resolve,Promise就进入了已兑现状态,后续的reject会被完全忽略,所以这行reject完全是多余的,建议删掉。
除此之外,用Promise包裹回调式API的思路是没问题的,很多时候我们处理不支持Promise的老库时都会这么做。
问题2:是否存在更简洁的方式将所有Mongoose请求整合到一个Promise中?
当然有!其实Mongoose本身就已经支持Promise了,根本不需要你手动用new Promise去封装它的查询方法。
优化方案1:直接使用Mongoose返回的Promise
Mongoose的查询方法(比如find())如果不传入回调函数,就会直接返回一个Promise。exec()方法也会返回Promise,所以你可以直接把这些查询结果当作Promise来用:
router.get("/test", function(req, res){ // 直接获取Mongoose查询的Promise,无需手动封装 const mainCategory = Maincategory.find().populate("subcategory").exec(); const itemQuery = Items.find({}); // 不传回调自动返回Promise Promise.all([mainCategory, itemQuery]) .then(function(allQueries){ // 用数组解构简化变量赋值 const [allCategories, allItems] = allQueries; const userId = "true"; const show = "list"; res.render("test.ejs", { allCategories, allItems, userId, show }); }) .catch(function(error){ console.log("error 6"); res.render("error.ejs", { error }); }); });
优化方案2:用async/await进一步简化
如果你的Node.js版本支持(现在几乎所有环境都支持了),用async/await可以让异步代码看起来更像同步代码,可读性更强:
router.get("/test", async function(req, res){ try { // 用await直接获取异步结果 const allCategories = await Maincategory.find().populate("subcategory").exec(); const allItems = await Items.find({}); const userId = "true"; const show = "list"; res.render("test.ejs", { allCategories, allItems, userId, show }); } catch (error) { console.log("error 6"); res.render("error.ejs", { error }); } });
这种写法完全避免了.then()链式调用,代码逻辑更直观,出错时直接用try/catch捕获,和同步代码的错误处理逻辑一致。
内容的提问来源于stack exchange,提问作者theliadir
相关产品推荐
相关产品推荐

