浏览器如何检测操作系统即将进入休眠/睡眠状态?如何在系统休眠前执行函数优雅关闭WebRTC连接?
Great question! Let's break this down into two clear parts: how browsers detect system sleep/hibernation, and how you can hook into those events to gracefully clean up your WebRTC connections.
The beforeunload event you tried only triggers when the user closes the tab, refreshes the page, or navigates away—so it won't catch system sleep/hibernation. Instead, modern browsers rely on the Page Lifecycle API to handle these low-power states.
Here's the key mechanism:
- When the operating system is about to sleep or hibernate, the browser will trigger the
freezeevent for all active tabs. This event signals that the page is about to enter a frozen state where no scripts run until the system resumes. - For older browsers that don't support
freeze, you can use thevisibilitychangeevent as a fallback: system sleep will almost always mark the page as "hidden", which triggers this event (though note it also fires when switching tabs or minimizing the browser).
Major browsers like Chrome/Edge 68+, Firefox 75+, and Safari 14.1+ fully support the freeze and resume events from the Page Lifecycle API.
To gracefully close your WebRTC connections before the system sleeps, you'll want to listen for the freeze event (with visibilitychange as a safety net) and run your cleanup logic synchronously (since the browser will pause the page right after the event fires).
Here's a practical code example:
// Helper function to clean up WebRTC resources function cleanUpWebRTC() { // Close all active RTCPeerConnection instances if (window.peerConnections) { window.peerConnections.forEach(connection => { if (connection.connectionState !== 'closed') { connection.close(); } }); window.peerConnections = []; } // Stop and release local media tracks if (window.localMediaStream) { window.localMediaStream.getTracks().forEach(track => { track.stop(); }); window.localMediaStream = null; } console.log('WebRTC connections cleaned up successfully.'); } // Primary handler: Listen for the freeze event (system sleep/hibernation) document.addEventListener('freeze', () => { console.log('System is entering sleep/hibernation. Cleaning up WebRTC...'); cleanUpWebRTC(); }); // Optional: Listen for resume to reinitialize connections if needed document.addEventListener('resume', () => { console.log('System resumed. Reinitializing WebRTC connections...'); // Add your logic here to restart WebRTC sessions }); // Fallback for older browsers: Use visibilitychange document.addEventListener('visibilitychange', () => { if (document.hidden) { console.log('Page hidden (possible system sleep). Running WebRTC cleanup...'); cleanUpWebRTC(); } });
Important Notes:
- Keep cleanup synchronous: The
freezeevent's callback must run synchronously—async operations like fetch calls might not complete before the page is frozen. Closing WebRTC connections and stopping media tracks are sync operations, so they work perfectly here. - Test edge cases: On Safari, you might see
pagehidefire beforefreezeduring system sleep. If you need full Safari compatibility, add a listener forpagehideas well (but be aware it also triggers when the tab is closed). - Avoid over-cleaning: If you're using the
visibilitychangefallback, remember it triggers when switching tabs too—so you might want to add additional checks (like tracking how long the page has been hidden) if you only want to clean up on system sleep.
内容的提问来源于stack exchange,提问作者user1591482

