Socket.io搭配双Promise与双Socket事件时无法正常运行问题问询
问题原因
- 事件监听器注册滞后:前端在Socket连接建立后立即触发
phone:submitted事件,但后端的事件监听器是在client.login调用对应getPhoneNumber/getAuthCode方法时才注册的,此时前端发送的事件已经执行完毕,没有被监听器捕获,导致对应Promise永远无法resolve,流程卡住。 - 登录流程顺序依赖:tdl的
client.login会按顺序执行回调返回的方法:先调用getPhoneNumber拿到手机号请求Telegram下发验证码,请求成功后才会调用getAuthCode方法,此时才会注册验证码事件监听器,若验证码提前提交也会丢失。同时你当前的前端代码仅提交了手机号,没有后续提交验证码的逻辑,也会导致完整登录流程无法走完。 - 会话复用的错觉:如果本地已有Telegram登录缓存,仅配置
getPhoneNumber时tdl会直接复用现有会话完成登录,不需要走验证码校验流程,所以看起来运行正常;当你同时配置getAuthCode后,tdl会触发完整校验流程,必须拿到验证码才能完成登录,进一步放大了前面的问题。 - 监听器未清理:使用
socket.on注册的是持久监听器,多次连接会导致监听器重复注册,引发内存泄漏和逻辑冲突。
修复方案
核心逻辑是提前注册好两个事件的一次性监听器,避免事件丢失,调整后的后端代码如下:
io.on('connection', async (socket) => { console.log('a user connected'); // 提前初始化Promise和resolve引用 let resolvePhone, resolveCode; const phonePromise = new Promise((resolve) => resolvePhone = resolve); const codePromise = new Promise((resolve) => resolveCode = resolve); // 提前注册一次性监听器,事件触发直接resolve对应Promise socket.once('phone:submitted', (phone) => resolvePhone(phone)); socket.once('code:submitted', (code) => resolveCode(code)); // 监听连接断开,拒绝Promise避免内存泄漏 socket.on('disconnect', () => { phonePromise.catch(() => {}); codePromise.catch(() => {}); }); try { await client.login(() => ({ getPhoneNumber: () => phonePromise, getAuthCode: () => codePromise })); console.log('登录成功'); } catch (err) { console.error('登录失败:', err); } });
同时需要调整前端逻辑:不要在连接建立后立即提交手机号,改为用户主动输入手机号点击提交后再触发phone:submitted事件,收到后端提示验证码已下发的通知后,再让用户输入验证码提交触发code:submitted事件。
内容的提问来源于stack exchange,提问作者user253867
相关产品推荐
相关产品推荐

