手动设置PeerJS ID后出现Cannot read properties of undefined错误求助
手动设置PeerJS Peer ID时调用call方法出现"无法读取未定义的属性(读取'on')"错误
问题重现
自动生成Peer ID的代码可正常运行:
useEffect(() => { const peer = new Peer(); peer.on("open", (id) => { console.log(id); }) }, [])
但手动指定ID后,在通过useRef获取peer实例的call函数中抛出错误:
useEffect(() => { // 手动设置ID const peer = new Peer("set-id-873923"); peer.on("open", (id) => { console.log(id); }) }, [])
call函数代码:
const call = (remotePeerId) => { var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; getUserMedia({ video: true, audio: true }, (mediaStream) => { currentUserVideoRef.current.srcObject = mediaStream; currentUserVideoRef.current.play(); const call = peerInstance.current.call(remotePeerId, mediaStream); call.on("stream", (remoteStream) => { remoteVideoRef.current.srcObject = remoteStream; remoteVideoRef.current.play(); }); });
错误信息:"Cannot read properties of undefined (reading 'on')"(中文:无法读取未定义的属性(读取'on'))
问题根源
手动指定Peer ID时,PeerJS需要向PeerServer注册该ID,这个过程是异步的。如果在peer实例的open事件触发前(即初始化未完成)就调用peerInstance.current.call,此时要么peerInstance.current还未被赋值,要么call方法返回undefined,导致后续调用call.on时触发错误。
自动生成ID时,PeerServer会快速分配一个可用的随机ID,初始化速度快,所以不容易触发这个时序问题,但这只是偶然情况,并非正确实现方式。
解决方案
1. 延迟赋值useRef,确保Peer实例初始化完成
只有在open事件触发后,才将Peer实例赋值给useRef,保证后续调用时实例处于可用状态:
const peerInstance = useRef(null); useEffect(() => { const peer = new Peer("set-id-873923"); peer.on("open", (id) => { console.log("Peer ID初始化完成:", id); peerInstance.current = peer; // 初始化完成后再赋值 }); // 组件卸载时清理Peer实例 return () => { if (peerInstance.current) { peerInstance.current.destroy(); peerInstance.current = null; } }; }, []);
2. 在call函数中增加实例有效性检查
调用call前先验证peerInstance.current是否存在,避免无效调用:
const call = (remotePeerId) => { if (!peerInstance.current) { console.error("Peer实例尚未初始化,请稍后重试"); return; } var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; getUserMedia({ video: true, audio: true }, (mediaStream) => { currentUserVideoRef.current.srcObject = mediaStream; currentUserVideoRef.current.play(); try { const call = peerInstance.current.call(remotePeerId, mediaStream); call.on("stream", (remoteStream) => { remoteVideoRef.current.srcObject = remoteStream; remoteVideoRef.current.play(); }); // 监听呼叫错误 call.on("error", (err) => { console.error("呼叫失败:", err); }); } catch (err) { console.error("发起呼叫出错:", err); } }, (err) => { console.error("获取媒体流失败:", err); }); };
3. 处理Peer ID冲突情况
手动指定的ID可能已被占用,需监听error事件处理该场景:
peer.on("error", (err) => { if (err.type === "unavailable-id") { console.error("该Peer ID已被占用,请更换ID"); // 可在此处自动生成新ID或提示用户更换 } else { console.error("Peer实例错误:", err); } });
内容的提问来源于stack exchange,提问作者Vivaan Kumar
相关产品推荐
相关产品推荐

