怎么在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 这样的服务器端环境设计的,它使用 exports 或 module.exports 来导出模块。
我们会惊奇的发现 这个辨析后端的代码是模块化的代码,远远不是我们想要的代码
当然这里我们可以采用不适用模块化的代码,不使用exports 或 module.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 对象:
| 事件 | 事件处理程序 | 描述 |
|---|---|---|
| open | Socket.onopen | 连接建立时触发 |
| message | Socket.onmessage | 客户端接收服务端数据时触发 |
| error | Socket.onerror | 通信发生错误时触发 |
| close | Socket.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…