useEffect用async/await时WebRTC清理报createOffer空值错误如何解决
useEffect中async/await场景下WebRTC资源清理空引用问题修复
问题根因
报错 TypeError: Cannot read properties of null (reading 'createOffer') 的核心原因是 异步执行和组件清理的时序冲突:组件卸载触发清理函数时,pc实例已经被置空,但effect内的异步函数还在执行队列中,等await操作resolve后继续执行到pc.createOffer()等访问pc的逻辑时,就会触发空引用错误。
原有代码存在三个核心缺陷:
- 异步逻辑没有感知组件卸载状态,组件销毁后仍会继续执行后续WebRTC操作
- 资源实例作用域不合理,清理逻辑和异步逻辑共享外层可变的
pc变量,置空后异步流程无校验直接访问 - 清理逻辑不完整,没有在组件卸载时中断未完成的异步流程,也没有完整释放摄像头、麦克风、PeerConnection资源
正确实现代码
useEffect(() => { // 组件挂载状态标记,用于阻断卸载后的异步逻辑执行 let isMounted = true; let pc = null; let localStream = null; const initWebRTC = async () => { try { pc = new RTCPeerConnection(); if (!callUserFlag) return; // 申请媒体权限 localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }); // 异步返回后先校验挂载状态,已卸载则直接释放资源终止流程 if (!isMounted) { localStream.getTracks().forEach(track => track.stop()); pc.close(); return; } // 绑定本地流 localVideoRef.current.srcObject = localStream; localStream.getTracks().forEach(track => { pc.addTrack(track, localStream); }); // 创建offer前再次校验挂载状态 if (!isMounted) return; const offer = await pc.createOffer(); await pc.setLocalDescription(offer); // 发送信令前最后校验挂载状态 if (!isMounted) return; socket.emit("call user", { offer: offer, toSocket: socketId }); } catch (err) { // 组件卸载触发的错误不需要打印日志 if (isMounted) { console.error("WebRTC初始化失败: ", err); } } }; initWebRTC(); // 资源清理函数 return () => { isMounted = false; // 关闭PeerConnection if (pc) { pc.close(); pc = null; } // 停止所有媒体轨道,释放摄像头/麦克风权限 if (localStream) { localStream.getTracks().forEach(track => track.stop()); localStream = null; } // 清空视频元素绑定的流 if (localVideoRef.current) { localVideoRef.current.srcObject = null; } }; }, [callUserFlag, socketId]);
关键实现要点
- 所有
await异步节点执行完成后,必须先校验组件挂载状态,组件已卸载时立刻释放已申请的资源,终止后续流程,避免访问已被清理的空实例 pc、localStream这类可变资源要定义在useEffect的作用域内部,避免多次渲染、多个effect实例共享外层变量导致的状态混乱- 资源清理必须覆盖所有申请的资源:RTCPeerConnection必须调用
close()方法,媒体轨道必须调用stop()方法,否则会出现摄像头/麦克风常驻占用、页面内存泄漏的问题 - useEffect的依赖数组需要加入内部用到的
callUserFlag、socketId变量,避免闭包捕获旧值导致逻辑异常
内容的提问来源于stack exchange,提问作者Tytus Bomba
相关产品推荐
相关产品推荐

