如何将循环中使用闭包的数据库异步保存代码转换为Promise
Hey there! Let's refactor that callback-heavy code to use Promises—it'll make it cleaner, easier to read, and give you proper error handling instead of just throwing errors which can crash your server. Here's how to do it right:
First, remember that Mongoose's save() method returns a Promise when you don't pass a callback function. That's the key here. We can leverage this along with Promise.all() to handle all your category saves in parallel, and we won't need that closure hack anymore.
Option 1: Using .then() chains
article.save() .then(newArticle => { console.log('article created ', newArticle._id); // Create an array of Promises for each category save const categorySavePromises = categories.map(category => { const categoryArticle = new category_article_model({ category: category, article_id: newArticle._id }); return categoryArticle.save(); }); // Wait for all category saves to complete before sending the response return Promise.all(categorySavePromises) .then(() => newArticle); // Pass the newArticle through to the next step }) .then(newArticle => { res.status(res.statusCode).send(newArticle); }) .catch(err => { // Handle any error that occurs during article or category saves console.error('Save error:', err); res.status(500).send('Failed to save article and associated categories'); });
Option 2: Using async/await (even cleaner!)
If your outer function is marked as async, you can use await to make the code look synchronous while still being asynchronous:
try { const newArticle = await article.save(); console.log('article created ', newArticle._id); // Map each category to a save Promise const categorySavePromises = categories.map(category => { const categoryArticle = new category_article_model({ category: category, article_id: newArticle._id }); return categoryArticle.save(); }); // Wait for all category saves to finish await Promise.all(categorySavePromises); // Send the response once everything is done return res.status(res.statusCode).send(newArticle); } catch (err) { console.error('Save error:', err); return res.status(500).send('Failed to save article and associated categories'); }
Why this works better than your original code:
- No more closure needed: The
mapfunction captures eachcategoryvalue correctly, so we don't have to use an IIFE to fix loop variable scoping issues. - Proper error handling: All errors (whether saving the article or any category) are caught in one place, so you can send a meaningful error response instead of crashing your server.
- Clearer flow:
Promise.all()makes it explicit that we're waiting for all category saves to complete before sending the response, which matches your original intent but is much easier to follow.
内容的提问来源于stack exchange,提问作者kittu
相关产品推荐
相关产品推荐

