Node.js/Express错误捕获最佳实践:MongoDB连接场景的正确实现
Hey there! Let's walk through the best practices for handling MongoDB connection errors in your Express app to keep it running reliably, without relying on repetitive if/else blocks. First, let's fix a quick issue in your connection string: it should be mongodb://localhost/db (three slashes, not two) — that's a common typo that causes connection failures right off the bat.
1. Use Promise/Async-Await with Express Error Handling Middleware
Modern MongoDB drivers support Promises, so we can ditch callback-based code for async/await, which makes error handling cleaner. The key here is to leverage Express's built-in error-handling middleware to centralize error logic instead of handling it in every route or connection callback.
First, create a dedicated database connection module (e.g., db.js) to separate connection logic from your routes:
const { MongoClient } = require('mongodb'); const DB_URI = "mongodb://localhost/db"; let dbInstance; // Connect to MongoDB and cache the connection async function connectToDB() { try { const client = await MongoClient.connect(DB_URI); dbInstance = client.db(); console.log("✅ Connected to MongoDB successfully"); return dbInstance; } catch (err) { console.error("❌ MongoDB connection failed:", err); // Optional: Add retry logic here if you want the app to retry connecting // setTimeout(connectToDB, 5000); throw err; // Propagate the error to let Express handle it } } // Get the cached DB instance function getDB() { if (!dbInstance) { throw new Error("Database not connected yet — call connectToDB() first"); } return dbInstance; } module.exports = { connectToDB, getDB };
Then, in your main Express app file (e.g., app.js), initialize the DB connection before starting the server, and set up a global error handler:
const express = require('express'); const { connectToDB, getDB } = require('./db'); const app = express(); // Initialize DB connection and start server (async () => { try { await connectToDB(); app.listen(3000, () => console.log("🚀 Server running on port 3000")); } catch (err) { console.error("❌ Failed to start server: DB connection error", err); process.exit(1); // Exit if we can't connect to the database (optional, based on your needs) } })(); // Example route using the DB app.get('/api/data', async (req, res, next) => { try { const db = getDB(); const data = await db.collection('your-collection').find().toArray(); res.json(data); } catch (err) { next(err); // Pass the error to the global handler } }); // Express error-handling middleware (must have 4 parameters) app.use((err, req, res, next) => { console.error("Request error:", err); // Return user-friendly error based on environment const statusCode = err.statusCode || 500; res.status(statusCode).json({ message: process.env.NODE_ENV === 'production' ? "Internal Server Error" : err.message, error: process.env.NODE_ENV === 'production' ? {} : err.stack }); });
2. Add Global Unhandled Error Listeners
Even with careful try/catch handling, there might be uncaught exceptions or unhandled promise rejections. Add these listeners to your main app file to prevent silent crashes:
// Catch unhandled promise rejections process.on('unhandledRejection', (reason, promise) => { console.error("Unhandled Rejection at:", promise, "Reason:", reason); // Optional: Clean up resources (e.g., close DB connections) before exiting }); // Catch uncaught synchronous exceptions process.on('uncaughtException', (err) => { console.error("Uncaught Exception:", err); // Exit the process safely — Node.js becomes unstable after uncaught exceptions process.exit(1); });
Why This Is Better Than If/Else
- Centralized error handling: No need to write
if (err)in every callback or route — all errors flow to one middleware. - Cleaner, more readable code: Async/await makes asynchronous logic look synchronous, avoiding callback hell.
- Resilience: You can add retry logic for DB connections, and global listeners catch edge cases that might crash your app.
- Separation of concerns: DB connection logic is isolated, making it easier to test and maintain.
内容的提问来源于stack exchange,提问作者JoeBoggs

