使用Promise基于ObjectId查询数据时无法返回结果的问题
问题:Promise查询MongoDB数据成功但无法返回结果
我尝试通过Promise基于ObjectId从数据库中获取数据,数据库已成功查询到数据,但无法返回结果。以下是我的实现代码:
getScreenDetails = function(req, res) { return new Promise((resolve, reject) => { screen.find({ "_id": req.params.id }) .then((response) => { resolve(response); }, (err) => { reject({ status: "failure", error: err }); }) }); };
解决方案
我来帮你分析几个可能的原因和对应的解决办法:
1. find返回数组而非单个文档,导致后续处理误解
你当前用的screen.find()方法会返回匹配条件的所有文档组成的数组,哪怕只有一条数据。如果你的场景是获取单条详情,建议改用findById或者findOne,这两个方法返回单个文档,更符合业务逻辑:
getScreenDetails = function(req, res) { return new Promise((resolve, reject) => { // 改用findById,自动处理ObjectId转换 screen.findById(req.params.id) .then((response) => { // 额外判断文档是否存在 if (!response) { return reject({ status: "failure", error: "未找到对应的屏幕数据" }); } resolve(response); }) .catch((err) => { reject({ status: "failure", error: err.message }); }); }); };
2. 未正确处理ObjectId类型匹配
虽然Mongoose通常会自动把字符串类型的_id转换为ObjectId,但某些情况下(比如使用原生MongoDB驱动)可能需要手动转换。如果遇到类型不匹配的问题,可以显式转换:
const { ObjectId } = require('mongoose'); // 先导入ObjectId getScreenDetails = function(req, res) { return new Promise((resolve, reject) => { screen.find({ "_id": ObjectId(req.params.id) }) .then((response) => { resolve(response); }) .catch((err) => { reject({ status: "failure", error: err.message }); }); }); };
3. 调用Promise时未正确获取结果
你定义了返回Promise的函数,但如果调用时没有用await或者.then()来处理,就无法拿到返回值。比如在路由中应该这样调用:
// 用async/await的方式 app.get('/screens/:id', async (req, res) => { try { const screenData = await getScreenDetails(req, res); res.status(200).json({ status: "success", data: screenData }); } catch (error) { res.status(400).json(error); } }); // 或者用.then().catch()的方式 app.get('/screens/:id', (req, res) => { getScreenDetails(req, res) .then(screenData => res.status(200).json({ status: "success", data: screenData })) .catch(error => res.status(400).json(error)); });
4. 简化Promise写法(可选优化)
因为Mongoose的查询方法本身就返回Promise,你不需要手动包裹一层Promise,可以简化代码,让它更易读:
getScreenDetails = async function(req, res) { try { const screenData = await screen.findById(req.params.id); if (!screenData) { throw new Error("未找到对应的屏幕数据"); } return screenData; } catch (err) { throw { status: "failure", error: err.message }; } };
内容的提问来源于stack exchange,提问作者Shaik Nizamuddin
相关产品推荐
相关产品推荐

