【问题标题】:Nodejs ws module: Heartbeat in TypeScriptNodejs ws 模块:TypeScript 中的心跳
【发布时间】:2020-01-14 07:05:43
【问题描述】:

我目前正在使用 TypeScript 在 NodeJs 上运行 WebSocket 服务器。作为 WebSocket 服务器实现,我使用的是ws。除此之外,我使用@types/ws 包进行打字。 我希望服务器定期向每个连接的客户端发送一个 ping 包。 ws 模块的自述文件已经在 J​​avaScript 中提供了一个示例实现,我也想使用它。 您可以找到示例实现here

我面临的问题是示例实现将“isAlive”属性添加到套接字对象中,这在 TypeScript 中显然无法做到,因为套接字类不存在“isAlive”属性。

我的问题: 将此属性添加到套接字类的最佳方法是什么?由于我将这些套接字对象作为参数传递,因此我想避免向我的所有文件添加某种额外的导入,这些文件以某种方式与套接字一起工作。

我想避免为此将套接字对象类型转换为任何类型。

我尝试围绕 ws 实现一个包装类,这样我就可以实例化我的 WebSocket 类并在整个应用程序中使用它。

我的班级是这样的

import * as ws from "ws";


export default class WebSocketServer {
  private wss: ws.Server;
  private onSubscription: (socket: ws, deviceId: string, topicFilter: string) => void;

  constructor(port: number, onSubscription: (socket: ws, deviceId: string, topicFilter: string) => void) {
    this.wss = new ws.Server({ port });
    this.onSubscription = onSubscription;
    const conhandler = this.handleConnection.bind(this);
    this.wss.on("connection", conhandler);
  }

  public static init(onSubscription: (socket: ws, deviceId: string, topicFilter: string) => void): WebSocketServer {
    const port: number = Number(process.env.WSS_PORT);
    if (!port) {
      throw new Error("Unable to create the WebSocket server: Environment variable \"WSS_PORT\" is missing");
    }

    const server: WebSocketServer = new WebSocketServer(port, onSubscription);

    console.info(`Websocket Server listening on port ${port}`);
    return server;
  }


  private handleConnection(socket: ws): void {
    const messageHandler: (socket: ws, data: ws.Data) => void = this.handleMessage.bind(this);
    socket.on("message", data => messageHandler(socket, data));

    /* This is where I try to add the isAlive attribute to a socket object */
    /* but since ws does not have an attribute isAlive, TypeScript complains */
    socket.on("pong", () => socket.isAlive = true);
  }


  private handleMessage(socket: ws, data: ws.Data): void {
    /* Do stuff with the message */
  }


  public quit() {
    this.wss.close();
  }
}

编辑

正如评论者所说,我尝试了声明合并。我创建了一个名为“Augment.ts”的新文件并添加了以下代码:

import * as ws from "ws";
declare module "ws" {
  interface WebSocket {
    isAlive: boolean;
  }
}

在包含我的 WebSocketServer 类的文件中,我添加了 Augment.ts 文件的导入,如下所示:import "./Augment"。结果是另一个错误消息(但以某种方式说明相同?): Property 'isAlive' does not exist on type 'import("c:/path/to/project/node_modules/@types/ws/index.d.ts")'.ts(2339)

【问题讨论】:

  • 很遗憾我现在无法测试它,但我想您可以在与库中定义的相同命名空间中重新声明项目中的 Socket 接口,并为其添加 isAlive 属性.查看this page 了解更多信息。
  • 我可以假设这是一个编译时错误吗?我正在尝试将相同的示例从 js 转换为 typescript。您的示例粘贴到我的 ubuntu node.js./typescript 项目中并且编译没有错误(即使没有增强更改)。可能是环境问题?我不确定你的订阅/处理程序方法,所以我看看我是否可以简化代码来测试它

标签: node.js typescript websocket ws


【解决方案1】:

我通过创建一个扩展 Web Socket 的自定义 Socket 接口让它工作。

interface CustomSocket extends WebSocket {
    isAlive: boolean
}
export default class WebSocket {
    private heartbeat: ReturnType<typeof setInterval>
    private wss: WebSocket.Server


    constructor(port: number) {
        this.wss = new WebSocket.Server({port});

        this.wss.on('connection', this.handleConnection)
    }

    private handleConnection(socket: CustomSocket) {
        socket.on('pong', () => socket.isAlive = true)
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-25
    • 2012-10-09
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    • 2016-02-09
    • 1970-01-01
    • 2013-03-08
    相关资源
    最近更新 更多