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

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插件node

安装

cnpm i -S express-ws
复制代码

操做

使用express-ws插件对app进行操做,对于不是ts环境下的经过web

import express from 'express';
import expressWs from 'express-ws';
const app = express();
app = expressWs(app);
复制代码

对于 ts 环境下的操做express

import * as express from 'express';
import * as expressWs from 'express-ws';
const appBase = express();
// 引入 websocket
let wsInstance = expressWs(appBase);
let { app } = wsInstance;
复制代码

获取到实例以后,能够经过app.ws进行操做了npm

// 设置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传递给该函数,已达到模块划分的目的.bash

// 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链接websocket

ws.close();
复制代码

客户端的API

websocket实例化

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

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');
复制代码