基于Express.js与Mongoose的Node.js系统通知实现方案咨询
Hey there! I’ve built similar systems for hospitality platforms before, so let’s break down four practical, production-ready approaches to get admins notified when a customer completes a room booking. Each has its own sweet spot, so you can mix and match based on your team’s workflow.
1. Real-Time WebSocket Notifications (Best for Active Admins)
If your admins are constantly logged into a dashboard, real-time pushes via Socket.io are perfect—they’ll see the alert instantly without refreshing the page.
Step 1: Set up Socket.io with Express
First, install the package:
npm install socket.io
Integrate it with your Express server (make sure to handle CORS for your admin frontend):
const express = require('express'); const http = require('http'); const { Server } = require('socket.io'); const app = express(); const server = http.createServer(app); const io = new Server(server, { cors: { origin: "http://your-admin-dashboard-url.com", // Replace with your admin frontend URL methods: ["GET", "POST"] } }); // Track connected admin sockets (add auth checks here!) const adminSockets = new Set(); io.on('connection', (socket) => { // Verify admin status (e.g., check JWT from handshake auth) const isAdmin = socket.handshake.auth.isAdmin; if (isAdmin) { adminSockets.add(socket.id); console.log(`Admin connected: ${socket.id}`); } socket.on('disconnect', () => { adminSockets.delete(socket.id); }); }); // Export io to use in Mongoose hooks module.exports = { app, server, io };
Step 2: Trigger Notifications from Mongoose
Add a post('save') middleware to your Booking model to emit a notification when a booking is confirmed:
const mongoose = require('mongoose'); const { io } = require('../server'); // Import your Socket.io instance const bookingSchema = new mongoose.Schema({ customerName: String, roomNumber: String, checkInDate: Date, checkOutDate: Date, status: { type: String, default: 'confirmed' } }); // After a booking is saved, notify connected admins bookingSchema.post('save', function(booking) { if (booking.status === 'confirmed') { io.to([...adminSockets]).emit('new-booking', { message: `New booking from ${booking.customerName} for room ${booking.roomNumber}`, bookingId: booking._id, timestamp: new Date() }); } }); module.exports = mongoose.model('Booking', bookingSchema);
Step 3: Listen for Notifications in Admin Frontend
Add this to your admin dashboard’s JavaScript to display alerts:
const socket = io('http://your-server-url.com', { auth: { isAdmin: true } // Pass your admin auth token here }); socket.on('new-booking', (notification) => { // Show a toast, update a notifications list, or play a sound alert(`Alert: ${notification.message}`); // Example: Append to a notifications panel document.getElementById('notifications-list').innerHTML += ` <div class="notification"> <p>${notification.message}</p> <small>${new Date(notification.timestamp).toLocaleString()}</small> </div> `; });
2. Email Notifications (Best for Passive Admins)
If admins aren’t always online, email notifications are reliable—they’ll get a direct message to their inbox. We’ll use Nodemailer for this.
Step 1: Install Nodemailer
npm install nodemailer
Step 2: Set Up Email Transporter
Create a helper file emailService.js (configure with your company’s SMTP or a service like SendGrid):
const nodemailer = require('nodemailer'); // Configure your email provider const transporter = nodemailer.createTransport({ host: 'smtp.your-company.com', port: 587, secure: false, // true for 465, false for other ports auth: { user: 'admin-notifications@your-company.com', pass: 'your-email-password-or-app-token' } }); // Send booking notification email async function sendBookingNotification(booking) { const mailOptions = { from: 'Room Booking System <admin-notifications@your-company.com>', to: 'admin1@your-company.com, admin2@your-company.com', // List of admin emails subject: `New Room Booking: ${booking.customerName}`, html: ` <h3>New Booking Confirmed</h3> <p><strong>Customer:</strong> ${booking.customerName}</p> <p><strong>Room:</strong> ${booking.roomNumber}</p> <p><strong>Check-in:</strong> ${new Date(booking.checkInDate).toLocaleDateString()}</p> <p><strong>Check-out:</strong> ${new Date(booking.checkOutDate).toLocaleDateString()}</p> <p>View details in the admin dashboard.</p> ` }; try { await transporter.sendMail(mailOptions); console.log('Notification email sent successfully'); } catch (error) { console.error('Failed to send email:', error); } } module.exports = { sendBookingNotification };
Step 3: Hook into Mongoose
Update your Booking model to call the email function on save:
const { sendBookingNotification } = require('../services/emailService'); bookingSchema.post('save', async function(booking) { if (booking.status === 'confirmed') { await sendBookingNotification(booking); } });
3. Database-Stored Notifications (Best for Audit Trails)
If you need a persistent record of all notifications (for later review or reporting), store them in MongoDB. Combine this with real-time pushes or let admins check a notifications page.
Step 1: Create a Notification Model
const mongoose = require('mongoose'); const notificationSchema = new mongoose.Schema({ type: { type: String, default: 'booking' }, message: String, booking: { type: mongoose.Schema.Types.ObjectId, ref: 'Booking' }, read: { type: Boolean, default: false }, createdAt: { type: Date, default: Date.now } }); module.exports = mongoose.model('Notification', notificationSchema);
Step 2: Create Notifications on Booking Save
const Notification = require('./Notification'); bookingSchema.post('save', async function(booking) { if (booking.status === 'confirmed') { await Notification.create({ message: `New booking from ${booking.customerName} for room ${booking.roomNumber}`, booking: booking._id }); } });
Step 3: Fetch Notifications in Admin Dashboard
Add Express routes to get unread notifications and mark them as read:
const Notification = require('../models/Notification'); // Get unread admin notifications (add auth middleware first!) app.get('/api/admin/notifications', async (req, res) => { const notifications = await Notification.find({ read: false }) .populate('booking') .sort({ createdAt: -1 }); res.json(notifications); }); // Mark notification as read app.patch('/api/admin/notifications/:id', async (req, res) => { const notification = await Notification.findByIdAndUpdate( req.params.id, { read: true }, { new: true } ); res.json(notification); });
4. Combine Approaches (Most Robust)
For a full-featured system, mix all three:
- Create a database notification record (for audit trails)
- Emit a real-time WebSocket message (for active admins)
- Send an email (for offline admins)
This way, admins never miss a notification—whether they’re on the dashboard or away from their desk.
Pro Tips
- Add Authentication: Always verify admin status before sending notifications (use JWT or session auth for WebSocket connections and API routes).
- Error Handling: Wrap all async operations (email sending, database saves) in try/catch blocks to avoid crashing your server.
- Rate Limiting: If you get a high volume of bookings, add rate limits to prevent spamming admins with alerts.
内容的提问来源于stack exchange,提问作者MOona Rueda

