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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:40:09