React中使用Deepgram SDK时,如何重新连接已关闭的Socket?
Deepgram Live SDK 连接超时断开&重新连接后无法接收转录数据问题解决
问题根源分析
当前代码存在几个核心问题导致连接超时和重新连接失效:
- 全局变量
liveClient:跨组件或组件重新渲染时会复用旧实例,事件监听重复绑定,状态混乱 keepAlive()单次调用:该方法需要定时发送心跳包才能维持连接,单次调用无法阻止12秒超时- 缺乏实例清理机制:重新连接时未销毁旧实例,新实例的事件监听未正确绑定,导致无法接收转录数据
修复方案
1. 将liveClient转为组件状态
用useState存储客户端实例,避免全局变量带来的状态污染,确保每次重新连接都创建全新实例。
2. 定时发送心跳包
在连接建立后启动定时器,每10秒调用一次keepAlive(),确保在12秒超时前维持连接。
3. 新增手动连接函数
提供明确的connect方法,用于重新连接时销毁旧实例、创建新实例并绑定所有事件监听。
4. 完善清理机制
在组件卸载或连接关闭时,清理定时器、销毁客户端实例,避免内存泄漏。
修改后的完整代码
import { Dispatch, SetStateAction, useCallback, useEffect, useState } from 'react'; import { LiveClient, LiveTranscriptionEvent, LiveTranscriptionEvents, createClient } from '@deepgram/sdk'; const deepgram = createClient(process.env.NEXT_PUBLIC_DEEPGRAM_API_KEY || ''); function useDeepgram(setInputText: Dispatch<SetStateAction<string>>) { const [connectionStatus, setConnectionStatus] = useState<'open' | 'closed'>('closed'); const [liveClient, setLiveClient] = useState<LiveClient | null>(null); const [heartbeatTimer, setHeartbeatTimer] = useState<NodeJS.Timeout | null>(null); // 绑定事件监听的通用函数 const bindClientEvents = useCallback((client: LiveClient) => { client.on(LiveTranscriptionEvents.Open, () => { setConnectionStatus('open'); // 启动心跳定时器,每10秒发送一次 const timer = setInterval(() => { client.keepAlive(); }, 10000); setHeartbeatTimer(timer); }); client.on(LiveTranscriptionEvents.Transcript, (data: LiveTranscriptionEvent) => { if (data.type === 'Results' && data.channel.alternatives[0].transcript) { setInputText((prev) => `${prev} ${data.channel.alternatives[0].transcript}`); } }); client.on(LiveTranscriptionEvents.Close, () => { setConnectionStatus('closed'); if (heartbeatTimer) clearInterval(heartbeatTimer); setHeartbeatTimer(null); }); // 新增错误监听,便于排查问题 client.on(LiveTranscriptionEvents.Error, (error) => { console.error('Deepgram连接错误:', error); setConnectionStatus('closed'); }); }, [setInputText, heartbeatTimer]); // 初始化/重新连接函数 const connect = useCallback(() => { // 销毁旧实例 if (liveClient) { liveClient.finish(); } // 创建新实例 const newClient = deepgram.listen.live({ model: 'nova' }); setLiveClient(newClient); bindClientEvents(newClient); }, [liveClient, bindClientEvents]); // 组件挂载时自动连接 useEffect(() => { connect(); // 组件卸载时清理 return () => { if (liveClient) liveClient.finish(); if (heartbeatTimer) clearInterval(heartbeatTimer); }; }, []); const disconnect = useCallback(() => { setConnectionStatus('closed'); if (liveClient) liveClient.finish(); if (heartbeatTimer) clearInterval(heartbeatTimer); setHeartbeatTimer(null); }, [liveClient, heartbeatTimer]); const sendData = useCallback( (chunk: Blob) => { if (liveClient && connectionStatus === 'open') { liveClient.send(chunk); } }, [liveClient, connectionStatus] ); return { connectionStatus, sendData, disconnect, connect }; } export default useDeepgram;
关键修改说明
- 状态管理:用
useState管理liveClient和heartbeatTimer,确保状态可控 - 心跳机制:每10秒发送一次心跳包,避免12秒超时断开
- 实例清理:重新连接前销毁旧实例,避免资源占用和事件冲突
- 错误监听:新增
Error事件监听,便于排查连接异常问题 - 手动连接:暴露
connect方法,可通过按钮点击触发重新连接,确保新实例正确绑定事件
内容的提问来源于stack exchange,提问作者Balaji Sivasakthi
相关产品推荐
相关产品推荐

