Next.js应用暂停视频时触发DOMException错误的排查与解决
解决Next.js滑块视频组件切换时的DOMException错误
问题背景
我开发了一个Next.js应用,包含滑块组件,滑块内是带独立视频组件的博客式帖子。用户点击菜单按钮切换滑块(通过修改状态加载新帖子列表),滑块里的视频支持播放/暂停,切换幻灯片时会通过观察者暂停当前播放的视频。整体功能正常,但频繁操作切换滑块时,会抛出错误:
Uncaught (in promise) DOMException: The play() request was interrupted because the media was removed from the document
最终导致应用冻结无响应。
原因分析
play()是异步操作,用户切换导航时会出现以下流程:
- 视频元素被从DOM中移除
- play()的Promise完成后,尝试对已不存在的视频执行pause()等操作,引发DOM异常
解决方案(适配Chrome浏览器)
需要在视频组件卸载时清理未完成的异步操作,同时在操作视频元素前检查其是否仍存在于DOM中,具体修改如下:
修改后的视频组件代码
import { useEffect, useRef } from 'react'; const VideoComponent = () => { const videoRef = useRef(null); const playPromiseRef = useRef(null); const handlePlayPause = () => { const video = videoRef.current; if (!video) return; playPromiseRef.current = video.play(); if (playPromiseRef.current !== undefined) { playPromiseRef.current .then(() => { // 先检查视频元素是否仍在DOM树中,再执行后续操作 if (document.contains(video)) { video.pause(); video.currentTime = 0; } }) .catch((error) => { // 过滤掉因DOM移除导致的预期错误,避免无效日志 if (!(error.name === 'DOMException' && error.message.includes('media was removed from the document'))) { console.log('视频操作错误', error); } }); } }; useEffect(() => { return () => { // 组件卸载时主动清理 const video = videoRef.current; if (video && document.contains(video)) { video.pause(); video.currentTime = 0; } // 清空未完成的Promise引用 playPromiseRef.current = null; }; }, []); return <video ref={videoRef} src="your-video-url.mp4" />; }; export default VideoComponent;
关键修改点
- 用
useRef保存playPromise引用,方便组件卸载时跟踪状态 - 在
then回调中通过document.contains(video)校验元素存在性,避免操作已移除的DOM节点 - 组件卸载时主动暂停视频并重置进度,同时清空Promise引用
- 错误捕获中过滤掉预期的DOM移除错误,减少无效日志输出
内容的提问来源于stack exchange,提问作者robster9090
相关产品推荐
相关产品推荐

