Mongoose异步函数查询数据日志正常但返回undefined问题排查
Let's break down what's going wrong here and fix it step by step—since you're new to async programming, I'll keep this clear and straightforward.
The Core Problem
Your returnBlogThumbnails function is marked as async, but it doesn't actually return a value that resolves to your database results. Here's why:
- The
return docs;inside the.exec()callback only returns from that callback function, not from the outerreturnBlogThumbnailsfunction. - Since the database query is asynchronous, the outer function finishes executing immediately after calling
Blog.find().exec(), and because it has no explicitreturnstatement, it defaults to returningundefined. - You also included a
callbackparameter but aren't using it, while trying to use.then()(Promise syntax) when calling the function—mixing callback and Promise styles adds unnecessary confusion.
Solution 1: Use Mongoose's Built-in Promise Support (Recommended)
Mongoose queries natively return Promises, so you can simplify your function by returning the query directly. The async keyword is optional here (since we're returning a Promise already), but it doesn't hurt to keep it for consistency if you plan to add more async logic later.
async function returnBlogThumbnails(filter = "recent"){ console.log("returning blogs"); if(filter === "recent"){ // Return the Mongoose query Promise directly return Blog.find({}).sort('-date').exec(); } // Fallback for other filter values return []; }
Your existing call code will work perfectly with this fix (plus we'll add error handling to be safe):
app.get('/', (req, res)=> { console.log("go home"); database.returnBlogThumbnails().then((blogs) => { console.log(blogs); // Now this will log your actual docs! res.render('home', { blogs }); // Pass an object to render for template access }).catch(err => { // Handle database errors to avoid crashing your app console.error("Error fetching blogs:", err); res.status(500).send("Something went wrong loading blogs"); }); });
Solution 2: Manually Wrap the Callback in a Promise (For Learning)
If you want to understand how to convert callback-based code to Promises (a key async skill), you can wrap the .exec() call in a new Promise:
function returnBlogThumbnails(filter = "recent"){ console.log("returning blogs"); return new Promise((resolve, reject) => { if(filter === "recent"){ Blog.find({}).sort('-date').exec((err, docs) => { if(err){ // Reject the Promise if there's an error reject(err); } else { // Resolve the Promise with your results resolve(docs); } }); } else { // Resolve with an empty array for other filters resolve([]); } }); }
This works exactly the same as Solution 1 when called with .then(), but it makes explicit how async results are passed back using Promise resolvers.
Key Async Takeaways for Beginners
- Callback return values don't bubble up: The
returninside an async callback only affects that callback, not the parent function. - Use Promises or async/await consistently: Mixing callbacks and Promises leads to confusion and bugs. Mongoose supports Promises out of the box, so use that!
- Always handle errors: Add
.catch()to your Promise chains (ortry/catchif usingawait) to avoid unhandled errors crashing your app.
内容的提问来源于stack exchange,提问作者Wilson Lysford

