websocket是啥我就简单的说一下,这个大家知道的应该挺多的。那么首先它是一个协议,类似于我们的HTTP协议,但是不同的是HTTP协议是客户端向服务器端请求,然后服务器端响应并且只能响应一次,但是无法做到服务器端主动向浏览器端推送数据。那么websocket主要就是解决服务器端无法向客户端主动推送数据的。当我们需要保持一种长链接时,我们就需要用到websocket
使用场景如下:浏览器发起请求,这个请求会经历大量的计算,并且返回给浏览器当前计算到了哪一步,这个时候浏览器就可以展示一个弹窗告诉用户当前已经到了哪一步,适当的更可以展示一个进度条,避免用户因为请求时间太长看久了loading也会腻不是。
它的主要特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话
特点包括:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
这边是用node.js 的express框架进行操作,使用express-ws
插件
cnpm i -S express-ws
使用express-ws插件对app进行操作,对于不是ts环境下的通过
import express from 'express';
import expressWs from 'express-ws';
const app = express();
app = expressWs(app);
对于 ts 环境下的操作
import * as express from 'express';
import * as expressWs from 'express-ws';
const appBase = express();
// 引入 websocket
let wsInstance = expressWs(appBase);
let { app } = wsInstance;
获取到实例之后,可以通过app.ws进行操作了
// 设置websocket
app.ws('/autoSchedule', (ws, req) => {
ws.send('已连接');
});
之前看到有说可以通过router进行使用ws,因为router相当于一个mini 的app实例,但是我在ts环境下试了很多次都没有成功,比如说一下代码
import expres from 'express';
import expressWs from 'express-ws';
const router = expressWs(express().Router());
router.ws('/autoSchedule', (ws, req) => {
})
这种方式也是需要app做expressWS(app)
操作的。但是在ts下我没有试成功过,一直包的是router没有ws方法,或者是expressWs(express().Router())
操作时说router不是一个app实例。总之很神奇。那么我采用的方法是,将我的业务代码封装成一个大的函数然后通过模块导出,在app.ts文件下引用使用,这个操作的关键在于需要将app.ws('/autoSchedule',(ws: any, req: any))
回调函数中的ws传递给该函数,已达到模块划分的目的.
// app.ts
// 引入封装好的函数模块
import scheduleWs from './src/util/autoSchedule';
// 设置websocket
app.ws('/autoSchedule', (ws: any, req: any) => {
// 将 ws 传递给函数
scheduleWs(ws);
});
util/autoSchedule.ts
export default (ws: any) => {
ws.send('开始调用');
// 业务代码
}
websocket在执行send
方法,发送信息的时候,send
函数的参数只支持字符串、二进制数据。所以我一般会将所需要的数据转成 JSON字符串,然后在前端在解析,例如
// 服务器端
ws.send(JSON.stringify({
code: 0,
msg: '开始调度'
}));
// 客户端
ws.onmessage = (e: any) => {
let res: any = JSON.parse(e.data);
}
执行完全部任务时,记得关闭socket连接
ws.close();
websocket协议的接口地址是以 ws 开头
let ws = new WebSocket('ws://localhost:3000/autoSchedule');
switch (ws.readyState) {
case WebSocket.CONNECTING:
// do something
break;
case WebSocket.OPEN:
// do something
break;
case WebSocket.CLOSING:
// do something
break;
case WebSocket.CLOSED:
// do something
break;
default:
// this never happens
break;
}
监听连接开启
ws.onopen = () => {
console.log('已连接');
}
监听连接关闭
ws.onclose = () => {
console.log('已关闭');
}
监听连接发生错误
ws.onerror = (error: any) => {
console.log(error);
}
监听服务器端发来的消息
ws.onmessage = (e) => {
let res = e.data;
}
向服务器端发送消息
ws.send('hello world');