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

API请求中使用ws库的WebSocket回调内调用response.ok无响应问题

问题分析与解决方案

你的问题核心在于HTTP请求的响应周期和WebSocket的异步事件不匹配。虽然WebSocket能正常收发消息,但response.ok是在WebSocket的message回调里调用的——当这个回调触发时,embed_builder这个async函数早已经执行完毕,HTTP请求的上下文已经被服务器释放,所以你的响应根本发不出去。

具体原因

你当前的代码里,Ws.ws.on("open")和Ws.ws.on("message")都是注册异步事件监听,embed_builder函数会直接执行完这些监听注册就结束,不会等待WebSocket的消息返回。这时候服务器会认为请求已经处理完成,不会再接受后续的response.ok调用。

修复方案

用Promise把WebSocket的整个流程包裹起来,让embed_builder函数等待这个Promise resolve后再发送响应,把HTTP请求的响应周期和WebSocket的消息回调绑定起来。

修改后的代码示例:

public async embed_builder ({ request, response }: HttpContextContract) {
  const payload = request.body();

  // 用Promise包裹WebSocket的消息等待逻辑
  const socketResponse = await new Promise((resolve, reject) => {
    // 注册单次open事件,避免重复监听
    Ws.ws.once("open", () => {
      Ws.ws.send(JSON.stringify({ 
        socket_name: "embed-builder", 
        channel_id: payload.channel_id, 
        embed: payload.embed 
      }));
    });

    // 注册单次message事件,确保只处理当前请求的回复
    Ws.ws.once("message", (data: Buffer) => {
      const message = JSON.parse(data.toString());
      if (message.socket_name === "embed-builder") {
        if (!message.ok) {
          reject({ 
            error: { message: message.statusText }, 
            code: message.status 
          });
        } else {
          resolve("OK");
        }
      }
    });

    // 增加超时处理,避免请求无限挂起
    setTimeout(() => {
      reject({ error: { message: "WebSocket response timeout" }, code: 504 });
    }, 10000); // 10秒超时,可根据需求调整
  });

  return response.ok(socketResponse);
}

额外注意事项

  • 用once代替on注册事件监听,避免多次注册导致内存泄漏或重复响应的问题。
  • 必须添加超时处理,否则如果WebSocket一直不返回消息,该HTTP请求会持续占用服务器资源。
  • 如果Ws.ws是全局共享的WebSocket实例,要注意并发请求的消息混淆问题——这种场景下,建议为每个HTTP请求创建独立的WebSocket连接,或者在消息中加入唯一标识做路由区分。

内容的提问来源于stack exchange,提问作者user19325899

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 18:07:47