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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 20:06:01