WebSockets疑似干扰Travis-CI构建,导致超时挂起求助
Alright, let's break down why your Travis build is hanging even after tests pass—this is a common gotcha when adding Socket.io to a React/Node project, especially with CI environments like Travis.
The Likely Culprits
1. React Scripts Test is Stuck in Watch Mode
By default, react-scripts test runs in watch mode locally—it keeps the process alive to re-run tests when files change. While React Scripts is supposed to detect CI environments and exit automatically after tests finish, sometimes it needs a nudge. If Travis doesn't trigger that CI detection, the test process will sit idle waiting for input until it hits the 10-minute timeout.
2. Socket.io's Interval is Keeping the Node Process Alive
Looking at your server.js, you're setting up a setInterval for every connected socket:
setInterval(() => socket.emit("broadcast", user),1000);
If your tests are accidentally spinning up the backend server (even indirectly), this interval acts as an "active handle" that prevents Node.js from terminating the process. Worse, you're not clearing the interval when the socket disconnects—so even after a client drops off, the timer keeps running, keeping the process alive indefinitely.
Fixes to Try
First: Force the Test Command to Exit in CI
This is the quickest fix to rule out the watch mode issue. You have two options:
Option 1: Update Your Test Command in package.json
Modify the test script to explicitly set the CI environment variable:
"test": "CI=true react-scripts test --env=jsdom"
Option 2: Add the CI Variable to .travis.yml
If you don't want to modify your package script, add the environment variable directly in your Travis config:
language: node_js node_js: - "stable" env: - CI=true before_script: - cd client - npm install script: - npm run test
Either way, this tells react-scripts test to run once and exit immediately after tests complete.
Second: Clean Up Socket.io Intervals
If your tests do need to start the backend server (or if it's being started accidentally), you need to clean up those intervals when sockets disconnect. Update your server.js connection logic to track and clear the timer:
io.on('connection', (socket) => { user.userCount++; socket.emit("broadcast", user); // Save the interval reference const broadcastTimer = setInterval(() => socket.emit("broadcast", user), 1000); socket.on("disconnect", () => { user.userCount--; user.activeUsers--; socket.emit("broadcast", user); // Clear the timer when the socket disconnects clearInterval(broadcastTimer); }); // Rest of your socket handlers... });
This ensures that when a client disconnects, the associated interval is cleaned up, so Node can terminate the process when it's done.
Bonus: Make Sure Tests Aren't Starting the Backend
Double-check your client test files and setup scripts—make sure none of them are importing or starting the server.js file. If they are, add a teardown step to shut down the server after tests finish:
// In your test setup file or individual test files afterAll(() => { // Replace with your actual server instance server.close(); // Also close the Socket.io server io.close(); });
Start with setting CI=true—that's almost certainly the immediate fix for your Travis timeout. If the problem persists, move on to cleaning up the Socket.io intervals.
内容的提问来源于stack exchange,提问作者Bob Brown

