在html中用ts封装websocket

409 阅读1分钟

怎么在html中使用ts

对于前端这里采用ts的形式去进行 websocket封装

对于这个ts来说,我们需要采用tsc编译 将其编译成js供浏览器识别

这里我尝试了一些方法

使用tsc

npm install tsc

直接安装tsc的形式,然后用tsc ts文件名直接编译ts文件的形式实现

实时性监听问题

为了更加的自动化一点 我采用chokidar第三方库监听ts文件的方式,当保存文件的时候进行tsc指令从而实现辨析

npm install chokidar

这里我们将这个watch.js启动即可实时编译的效果

//watch.js

const chokidar = require('chokidar');
const { spawn } = require('child_process');

console.log('Watching for changes...');

// 设置要监视的文件或目录
const watcher = chokidar.watch('webSocketClient.ts', {
  persistent: true
});

// 当文件被添加、修改或删除时触发
watcher.on('change', path => {
  console.log(`File ${path} has been changed`);
  const tscProcess = spawn('tsc', ['webSocketClient.ts'], { shell: true });

  tscProcess.stdout.on('data', (data) => {
    console.log(data.toString());
  });

  tscProcess.stderr.on('data', (data) => {
    console.error(data.toString());
  });

  tscProcess.on('close', (code) => {
    if (code !== 0) {
      console.error(`tsc process exited with error code ${code}`);
    }
  });

  tscProcess.on('error', (error) => {
    console.error(`Failed to start tsc process: ${error}`);
  });
});

但是这里我们会遇到一些问题

Uncaught ReferenceError: exports is not defined 

错误信息 Uncaught ReferenceError: exports is not defined 指出 JavaScript 环境中没有定义 exports 变量。这个错误通常发生在尝试在浏览器环境中运行模块化代码时,该代码原本是为 Node.js 这样的服务器端环境设计的,它使用 exportsmodule.exports 来导出模块。

我们会惊奇的发现 这个辨析后端的代码是模块化的代码,远远不是我们想要的代码

当然这里我们可以采用不适用模块化的代码,不使用exportsmodule.exports。改为使用一个全局变量来存储你的类定义。

但是吧,这里我还是想试试

所以这里我们可以采用配置tsconfig.json的形式将我们的编译产物编译成es6的形式即可

{
  "compilerOptions": {
    "module": "ES6" // 或 "CommonJS"
  }
}

完整的形式

{
"compilerOptions": {
  "target": "ES5", // 设置目标为 ES5,以确保兼容性
  "module": "ES6", // 设置模块为 ES6 模块
  "moduleResolution": "node", // 使用 Node.js 模块解析逻辑
  "outDir": "src/dist", // 指定输出目录
  "rootDir": "./src", // 指定源代码目录
  "esModuleInterop": true, // 启用 ES6 模块互操作性
  "allowSyntheticDefaultImports": true, // 允许从没有默认导出的模块中默认导入
  "forceConsistentCasingInFileNames": true, // 确保文件名大小写一致
  "strict": true, // 启用所有严格类型检查选项
  "skipLibCheck": true // 忽略所有声明文件的类型检查
},
"include": ["src/**/*"], // 包含 src 目录中的所有文件
"exclude": ["node_modules", "src/dist"] // 排除 node_modules 和 dist 目录
}
实时性监听(采用)

在这里实时性监听我在翻阅TypeScript 的官网的时候发现,原来TypeScript的编译器会自动检测文件更改时候自动编译

tsc --watch //tsc -w

至此浏览器可以正常的识别我们的ts文件,我们只需要在我们的html中加上一个引用即可

    <script type="module" src="dist/webSocketClient.js"></script>

或者使用

import { WebSocketClient } from './dist/webSocketClient.js';

使用import的形式也可以接受

对于websocket封装

浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。

当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

以下 API 用于创建 WebSocket 对象。

var Socket = new WebSocket(url, [protocol] );

以上代码中的第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。

WebSocket 事件

以下是 WebSocket 对象的相关事件。假定我们使用了以上代码创建了 Socket 对象:

事件事件处理程序描述
openSocket.onopen连接建立时触发
messageSocket.onmessage客户端接收服务端数据时触发
errorSocket.onerror通信发生错误时触发
closeSocket.onclose连接关闭时触发

WebSocket 方法

以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:

方法描述
Socket.send()使用连接发送数据
Socket.close()关闭连接

事件封装

对于这个websocket我们使用的时候必然会对其进行封装

这里我们对WebSocket 的事件做一个简单的封装

收件这个是Socket对象是我们建立的时候是直接返回的,事件为Socket连接状态中改变触发的

这里我们可以当作生命周期 既然是生命周期,我们则可以使用会调用函数的方法触发即可

对于回调函数这里选择维护一个方法队列是实现 当然我们可以使用EventTarget直接使用,不用自己手动封装(ps:推荐直接使用EventTarget)

最后就是直接用事件触发这个队列中注册的事件即可

this.socket.onmessage = event => {
    this.dispatchEvent('message', event);
    this.startHeartbeat();
};

事件的注册我们将其注册的事件给用户让用户自行决定

onmessage(callBack: Function) {
    this.addEventListener('message', callBack);
}

至此我们对事件进行简单的封装 并让其可以在websocket不同的时候触发自定义回调

断线重连

这里我们采用一个状态和定时器的形式去控制

通过定时器重新建立连接

//断线重连
private handleReconnect():void{
    if(this.reconnectAttempts<this.maxReconnectAttempts){
        this.reconnectAttempts++
        this.log('WebSocket', `正在尝试重新连接[handleReconnect]...    ${this.url}`);
        setTimeout(() => {
            this.connect()
        },this.reconnectInterval)
    }else{
        this.closeHeartbeat()
        this.log('WebSocket', `重新连接尝试次数过多,请检查网络[handleReconnect]...    ${this.url}`);
    }
}

心跳机制的话

也就是一个定时器间隔发送消息,确认服务器的状态 这里服务器收到消息也可以发送一个心跳消息回来保证稳定,这里只在客户端做演示

//开始心跳检测,定时发送心跳消息
private startHearbeat():void{
    if(this.stopWs) return
    if(this.heartbeatTimer) this.closeHeartbeat()

    this.heartbeatTimer = setInterval(() => {
        if(this.socket && this.socket.readyState === WebSocket.OPEN){
            this.socket.send(JSON.stringify({ type: 'heartBeat', data: {} }));
            this.log('WebSocket', '送心跳数据...');
        }else{
            console.error('[WebSocket] 未连接');
        }
    },this.heartbeatInterval)
}

至此我们实现了简单的websocket的封装

代码启动

前端

使用方法

npm i

//这里是为了监听ts变化
tsc -w

后端

npm i
node server.js

ps socket的封装参考 juejin.cn/post/737136…