You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

手动设置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 00:41:58