node.js Express框架中使用websoecket 包含 ts 和 非 ts 环境


title: node.js Express框架中使用websoecket 包含 ts 和 非 ts 环境
tags:
- node.js
- express

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();

客户端的API

websocket实例化

websocket协议的接口地址是以 ws 开头

let ws = new WebSocket('ws://localhost:3000/autoSchedule');

websocket 的状态

  • CONNECTING:值为0,表示正在连接
  • OPEN:值为1,表示连接成功,可以通信了
  • CLOSING:值为2,表示连接正在关闭
  • CLOSED:值为3,表示连接已经关闭,或者打开连接失败
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;
}

websocket.open

监听连接开启

ws.onopen = () => {
    console.log('已连接');
}

websocket.close

监听连接关闭

ws.onclose = () => {
    console.log('已关闭');
}

websocket.onerror

监听连接发生错误

ws.onerror = (error: any) => {
    console.log(error);
}

websocket.onmessage

监听服务器端发来的消息

ws.onmessage = (e) => {
    let res = e.data;
}

websocket.sned

向服务器端发送消息

ws.send('hello world');

你可能感兴趣的:(Node.js)