5月28日 00:22
How does Mongoose manage connections and handle errors?
Mongoose connection management and error handling are key parts of building stable applications. Properly handling connection states and errors can ensure application reliability.
Connection Management
Basic Connection
javascriptconst mongoose = require('mongoose'); // Basic connection mongoose.connect('mongodb://localhost:27017/mydb'); // Connection with options mongoose.connect('mongodb://localhost:27017/mydb', { useNewUrlParser: true, useUnifiedTopology: true, maxPoolSize: 100, serverSelectionTimeoutMS: 5000, socketTimeoutMS: 45000 });
Connection Event Listeners
javascript// Connection successful mongoose.connection.on('connected', () => { console.log('Mongoose connected to MongoDB'); }); // Connection error mongoose.connection.on('error', (err) => { console.error('Mongoose connection error:', err); }); // Connection disconnected mongoose.connection.on('disconnected', () => { console.log('Mongoose disconnected'); }); // Connection closed mongoose.connection.on('close', () => { console.log('Mongoose connection closed'); });
Connection Status Check
javascript// Check connection status console.log(mongoose.connection.readyState); // 0 = disconnected // 1 = connected // 2 = connecting // 3 = disconnecting // Helper function function isConnected() { return mongoose.connection.readyState === 1; } function isConnecting() { return mongoose.connection.readyState === 2; }
Error Handling
Connection Error Handling
javascript// Use try-catch to handle connection errors async function connectToDatabase() { try { await mongoose.connect('mongodb://localhost:27017/mydb'); console.log('Connected to MongoDB'); } catch (error) { console.error('Failed to connect to MongoDB:', error); process.exit(1); } } // Use Promise.catch mongoose.connect('mongodb://localhost:27017/mydb') .then(() => console.log('Connected')) .catch(err => console.error('Connection error:', err));
Query Error Handling
javascript// Query error handling async function findUser(userId) { try { const user = await User.findById(userId); if (!user) { throw new Error('User not found'); } return user; } catch (error) { if (error.name === 'CastError') { console.error('Invalid user ID format'); } else if (error.name === 'MongooseError') { console.error('Mongoose error:', error.message); } else { console.error('Unexpected error:', error); } throw error; } }
Validation Error Handling
javascript// Validation error handling async function createUser(userData) { try { const user = await User.create(userData); return user; } catch (error) { if (error.name === 'ValidationError') { const errors = {}; Object.keys(error.errors).forEach(key => { errors[key] = error.errors[key].message; }); console.error('Validation errors:', errors); throw { message: 'Validation failed', errors }; } throw error; } }
Duplicate Key Error Handling
javascript// Duplicate key error handling async function createUniqueUser(userData) { try { const user = await User.create(userData); return user; } catch (error) { if (error.code === 11000) { const field = Object.keys(error.keyPattern)[0]; const value = error.keyValue[field]; console.error(`Duplicate key error: ${field} = ${value}`); throw { message: `${field} already exists`, field }; } throw error; } }
Reconnection Mechanism
Auto Reconnect
javascript// Mongoose automatically reconnects by default mongoose.connect('mongodb://localhost:27017/mydb', { // Auto reconnect configuration autoReconnect: true, reconnectTries: Number.MAX_VALUE, reconnectInterval: 1000 });
Custom Reconnection Logic
javascriptlet reconnectAttempts = 0; const maxReconnectAttempts = 5; mongoose.connection.on('disconnected', () => { if (reconnectAttempts < maxReconnectAttempts) { reconnectAttempts++; console.log(`Attempting to reconnect (${reconnectAttempts}/${maxReconnectAttempts})...`); setTimeout(() => { mongoose.connect('mongodb://localhost:27017/mydb'); }, 1000 * reconnectAttempts); } else { console.error('Max reconnection attempts reached'); process.exit(1); } });
Connection Pool Management
Connection Pool Configuration
javascriptmongoose.connect('mongodb://localhost:27017/mydb', { // Connection pool configuration maxPoolSize: 100, // Maximum connections minPoolSize: 10, // Minimum connections maxIdleTimeMS: 30000, // Maximum idle time waitQueueTimeoutMS: 5000 // Wait queue timeout });
Monitor Connection Pool
javascript// Monitor connection pool status setInterval(() => { const poolStatus = { ready: mongoose.connection.client.topology.s.pool.totalConnectionCount, active: mongoose.connection.client.topology.s.pool.activeConnectionCount, idle: mongoose.connection.client.topology.s.pool.idleConnectionCount }; console.log('Connection pool status:', poolStatus); }, 60000);
Graceful Shutdown
Graceful Shutdown Handling
javascriptasync function gracefulShutdown() { console.log('Shutting down gracefully...'); try { // Close database connection await mongoose.connection.close(); console.log('MongoDB connection closed'); // Exit process process.exit(0); } catch (error) { console.error('Error during shutdown:', error); process.exit(1); } } // Listen for process exit signals process.on('SIGTERM', gracefulShutdown); process.on('SIGINT', gracefulShutdown);
Best Practices
- Always handle connection errors: Never ignore connection errors
- Use connection pools: Configure appropriate connection pool size
- Implement reconnection mechanism: Ensure app can recover from connection interruptions
- Graceful shutdown: Properly handle connection cleanup during app shutdown
- Monitor connection status: Regularly check connection health
- Categorized error handling: Take different handling strategies based on error types
- Logging: Record connection and error information for debugging
- Timeout configuration: Set reasonable timeout values to avoid long waits