React+PeerJS视频聊天中'call'事件未触发问题求助
PeerJS "call" 事件不触发问题排查与修复
核心问题分析
从你提供的Call Object能看到_open: false,说明发起呼叫时Peer实例还未完成与服务器的连接初始化。同时代码中存在事件绑定时机、Peer生命周期管理的问题,导致新用户无法收到呼叫事件。
具体修复方案
1. 提前绑定Peer事件,避免错过呼叫
当前peer.on('call')是在getUserMedia的回调里绑定的,但Peer初始化是异步的,可能在媒体流获取完成前,新用户的呼叫请求已经到达,此时事件处理器还未绑定,导致事件丢失。
修改useOnPeerEvents.js,在Peer创建后立即绑定call事件:
useEffect( () => { const host = process.env.REACT_APP_SERVER_HOST || window.location.hostname const port = process.env.REACT_APP_SERVER_PORT || window.location.port const peer = new Peer( socket.id , { path: '/peerjs', host , port } ); // 提前绑定call事件,确保不会错过呼叫 peer.on( 'call', ( call ) => { // 判断媒体流是否准备好,避免空指针 if (streamRef.current) { answerCall( call, streamRef, setStreams ) } else { // 缓存呼叫请求,等媒体流就绪后处理 const streamReadyHandler = () => { answerCall(call, streamRef, setStreams); streamRef.current.removeEventListener('loadedmetadata', streamReadyHandler); }; streamRef.current?.addEventListener('loadedmetadata', streamReadyHandler); } } ) navigator.mediaDevices.getUserMedia( { audio: true, video: true } ) .then( stream => { streamRef.current = stream setStreams( streams => [ ...streams, { stream: streamRef.current, id: currentId } ] ) socket.on( 'stream-ready', ( id ) => { connectToNewUser( id, streamRef.current, peer, setStreams ) }) socket.on( 'left-room', ( peerId ) => { removeStream( peerId, setStreams ) }) // 等待Peer初始化完成后再发送stream-ready peer.on('open', () => { socket.emit( 'stream-ready', roomId ) console.log( 'stream-ready' , peer.id ); }) } ) return () => { socket.off( 'left-room' ) socket.off( 'stream-ready' ) // 销毁Peer实例,避免内存泄漏和旧连接干扰 peer.destroy() } }, [ currentId, roomId, socket ])
2. 确保Peer初始化完成后再发起呼叫
现有用户发起peer.call时,必须确保目标Peer已经完成初始化(open事件触发)。需要在后端调整stream-ready的触发时机:
- 新用户的Peer触发
open事件后,再向房间内其他用户发送stream-ready通知,告知新用户的Peer ID。
3. 修复Call Object未打开的问题
从你提供的Call Object来看,_open: false说明呼叫发起时Peer还未连接到服务器。修改connectToNewUser函数,确保Peer处于连接状态再发起呼叫:
const connectToNewUser = ( id, stream, peer, setStreams ) => { console.log( 'connecting...', id, stream ); // 等待Peer连接完成后再发起呼叫 if (peer.open) { const call = peer.call( id, stream ) console.log( call ); call.on( 'stream', ( userVideoStream ) => { console.log( 'add'); addStream( userVideoStream, id, setStreams ) }) // 监听呼叫错误,排查问题 call.on('error', (err) => { console.error('Call error:', err); }); } else { // 缓存呼叫请求,等Peer连接完成后再发起 const connectHandler = () => { connectToNewUser(id, stream, peer, setStreams); peer.off('open', connectHandler); }; peer.on('open', connectHandler); } }
4. 添加错误监听排查问题
在Peer和Call实例上添加错误监听,帮助定位潜在问题:
// Peer实例错误监听 peer.on('error', (err) => { console.error('Peer error:', err); }); // Call实例错误监听(放在connectToNewUser里) call.on('error', (err) => { console.error('Call error:', err); });
验证要点
- 检查新用户的Peer ID是否正确传递给现有用户
- 确认现有用户发起呼叫时,双方Peer都处于
open状态 - 查看浏览器控制台的错误日志,排除网络或PeerJS服务器配置问题
内容的提问来源于stack exchange,提问作者user19138001
相关产品推荐
相关产品推荐

