Electron项目中Express服务端口无法关闭的技术求助
server.close(), Graceful Shutdown Tools) Let's break down why your Express server is sticking around and how to fix it. I've seen this exact issue in Electron apps where async operations and lingering connections prevent the server from shutting down properly.
Why Your Current Code Isn't Working
server.close()Doesn't Kill Active Connections
Express'sserver.close()only stops accepting new connections—it won't forcefully terminate existing ones. If your/testendpoint is handling a request (like thenewWin.reload()triggering a call), that connection stays open, keeping the server alive.- Async Operations Are Out of Sync
In your code,server.close()runs immediately after starting the new window and setting the timeout. TheloadURLand 5-second timeout are still running, so there might be active requests hitting the server when you try to close it. - Missing Connection Tracking
Without tracking open connections, you can't ensure they're all closed when shutting down the server.
Fixes to Try
1. Track & Destroy Active Connections
Add code to track all incoming connections, then destroy them when closing the server. This ensures no lingering connections keep the server alive:
// When you create your Express server const server = app.listen(9001); // Replace with your actual port const activeConnections = new Set(); // Track every new connection server.on('connection', (conn) => { activeConnections.add(conn); // Remove the connection when it closes naturally conn.on('close', () => activeConnections.delete(conn)); }); // Custom close function to handle connections function shutdownServer() { server.close((err) => { if (err) { console.error('Failed to close server:', err); return; } // Destroy all remaining active connections activeConnections.forEach(conn => conn.destroy()); console.log('Server closed completely'); }); }
Now replace your raw server.close() call with shutdownServer().
2. Sync Async Operations Before Closing
Your current code runs server.close() before the new window's loadURL completes and the 5-second timeout finishes. Wrap these async steps in a promise to ensure they're done before shutting down the server:
// Helper to wait for a window's URL to finish loading function waitForWindowLoad(win, url) { return new Promise(resolve => { win.webContents.once('did-finish-load', resolve); win.loadURL(url); }); } // Refactor your window logic to use async/await async function restartAppFlow() { // Close existing windows service.close(); newWin.close(); // Create and configure new window newWin = new BrowserWindow({ webPreferences: { nodeIntegration: true, alwaysOnTop: true, skipTaskbar: true }, show: false, frame: false, }); newWin.show(); newWin.setMenu(null); newWin.setSize(600, 400); newWin.setPosition(0, 0); // Wait for the URL to load completely await waitForWindowLoad(newWin, "http://192.168.6.58:5000/logout/192.168.4.216"); // Wait the 5 seconds, close the window, then shut down the server setTimeout(() => { newWin.close(); shutdownServer(); // Use the custom shutdown function from fix 1 }, 5000); } // Run the refactored flow restartAppFlow();
3. Verify No Duplicate Server Instances
Double-check that you're not calling app.listen() multiple times in your code. If you accidentally create multiple server instances on the same port, only the last one's close() call will work, leaving the older ones running. Add a console log when starting the server to confirm it's only initialized once.
4. Last Resort: Force Process Exit (Not Ideal)
If all else fails, you can force the Node.js process to exit after shutting down the server. This will release the port immediately, but it's a blunt tool that might interrupt unfinished operations:
shutdownServer(); // Give a small delay to let cleanup run, then exit setTimeout(() => process.exit(0), 1000);
Quick Note on Third-Party Tools
The graceful shutdown and kill-port packages might not work here because Electron's main process has unique event loop behavior—tracking connections manually gives you more control over the shutdown flow.
内容的提问来源于stack exchange,提问作者Terro

