Midway.js打通WebSocket前后端监听通道

您好, 如果喜欢我的文章或者想上岸大厂,可以关注公众号「量子前端」,将不定期关注推送前端好文、分享就业资料秘籍,也希望有机会一对一帮助你实现梦想

前言

WebSocket协议允许客户端和服务端持久化连接,这种可以持续连接的特性使得WebScoket特别适用于游戏或者聊天室的场景,同样也适用于订单提交完以后监听状态变化进行页面刷新的场景。

Midway中提供了对于ws模块的支持和封装,能够快速创建WebSocket服务。

服务端实现

我们采用Midway.js来实现服务端能力,首先创建一个项目:

npm init midway@latest -y

然后在项目中安装WebSocket的依赖包:

npm i @midwayjs/ws@3 --save
npm i @types/ws --save-dev

/src/configuration.ts中开启WebSocket组件:

// src/configuration.ts
import { Configuration } from '@midwayjs/core';
import * as ws from '@midwayjs/ws';@Configuration({imports: [ws],// ...
})
export class MainConfiguration {async onReady() {// ...}
}

然后我们开始写接口,首先在项目目录创建socket目录:

├── package.json
├── src
│   ├── configuration.ts          ## 入口配置文件
│   ├── interface.ts
│   └── socket                    ## ws 服务的文件
│       └── hello.controller.ts
├── test
├── bootstrap.js                  ## 服务启动入口
└── tsconfig.json

通过 @WSController 装饰器定义 WebSocket 服务:

import { WSController } from '@midwayjs/core';@WSController()
export class HelloSocketController {// ...
}

当有客户端连接时,会触发 connection 事件,我们在代码中可以使用 @OnWSConnection() 装饰器来修饰一个方法,当每个客户端第一次连接服务时,将自动调用该方法。

import { WSController, OnWSConnection, Inject } from '@midwayjs/core';
import { Context } from '@midwayjs/ws';
import * as http from 'http';@WSController()
export class HelloSocketController {@Inject()ctx: Context;@OnWSConnection()async onConnectionMethod(socket: Context, request: http.IncomingMessage) {console.log(`namespace / got a connection ${this.ctx.readyState}`);}
}

WebSocket 是通过事件的监听方式来获取数据。Midway 提供了 @OnWSMessage() 装饰器来格式化接收到的事件,每次客户端发送事件,被修饰的方法都将被执行。

import { WSController, OnWSMessage, Inject } from '@midwayjs/core';
import { Context } from '@midwayjs/ws';@WSController()
export class HelloSocketController {@Inject()ctx: Context;@OnWSMessage('message')async gotMessage(data) {return { name: 'harry', result: parseInt(data) + 5 };}
}

我们可以通过 @WSBroadCast 装饰器将消息发送到所有连接的客户端上。

import { WSController, OnWSConnection, Inject } from '@midwayjs/core';
import { Context } from '@midwayjs/ws';@WSController()
export class HelloSocketController {@Inject()ctx: Context;@OnWSMessage('message')@WSBroadCast()async gotMyMessage(data) {return { name: 'harry', result: parseInt(data) + 5 };}@OnWSDisConnection()async disconnect(id: number) {console.log('disconnect ' + id);}
}

至此,基础的WebSocket接口就开发好了。

  • 当客户端连接时,我们会打印namespace / got a connection
  • 当客户端发送消息时,我们会返回给客户端基于入参的编号附加5的结果;
  • 当客户端断开连接时,我们会打印disconnect

最后我们在服务端开启一个WebSocket服务:

/src/config/config.default.ts

// src/config/config.default
export default {// ...webSocket: {port: 3000,},
}

接下来我们前端来调用测试下。

前端实现

前端使用react,我们建一个新页面,在useEffect中开启ws服务:

  useEffect(async () => {const ws = new WebSocket(`ws://localhost:9999`);ws.onopen = () => {console.log('连接成功');ws.send(1);};ws.onmessage = (e) => {console.log('服务端响应:', e);};ws.onclose = (e) => {console.log('关闭连接,服务端响应:', e)}}, []);

这样我们在前端就可以打印出服务端返回的结果,同时服务端获取到了日志信息,前后端的WebSocket链路打通了。

前端:

image.png

开启了webSocket服务:

image.png

后端:

image.png

订单刷新

接下来我们模拟一个场景:当前端提交完订单后到了订单详情页,需要实时获取订单状态,如果订单申请通过,则展示成功信息,这里就不连接数据库了,直接在服务端维护一个对象来模拟:

import {WSController,Inject,OnWSConnection,OnWSMessage,OnWSDisConnection,
} from '@midwayjs/core';
import { Context } from '@midwayjs/ws';
import * as http from 'http';const orderInfo = {status: 'pending',id: 1,// ...orderInfo
};@WSController()
export class HelloSocketController {@Inject()ctx: Context;// 客户端第一次连接@OnWSConnection()async onConnectionMethod(socket: Context, request: http.IncomingMessage) {this.ctx.logger.info(`namespace / got a connection ${this.ctx.readyState}`);setTimeout(() => {orderInfo['status'] = 'success';}, 3000);}// 收到客户端消息@OnWSMessage('message')async gotMessage() {if (orderInfo.status === 'success') {return { result: true };}return { result: false };}// 客户端断开连接@OnWSDisConnection()async disconnect(id: number) {console.log('disconnect ' + id);}
}
  • 在后端mock一个orderInfo
  • WebSocket连接后,延迟三秒改变orderInfo的状态,模拟一个算法审核的时间;
  • 三秒后响应给前端新状态;

前端配合改造:

useEffect(async () => {const ws = new WebSocket(`ws://localhost:9999`);ws.onopen = () => {console.log('连接成功');timer.current = setInterval(() => {ws.send(1);}, 1000);};ws.onmessage = (e) => {console.log('服务端响应:', e);if (JSON.parse(e.data).result) {setOrderPass(true);}};ws.onclose = (e) => {console.log('关闭连接,服务端响应:', e);};}, []);return <>订单状态:{orderPass ? '通过' : '申请中'}</>;

改造后,前端页面刷新,三秒后订单状态异步更改为通过,达到了页面监听实时刷新的效果,这样的效果是不是比传统Http定时轮询性能更优呢?

image.png

结尾

本文通过Midway0~1打通前后端ws链路,并在最后通过实际业务场景展示了ws的优势以及与传统轮询方案的差异。

如果喜欢我的文章或者想上岸大厂,可以关注公众号「量子前端」,将不定期关注推送前端好文、分享就业资料秘籍,也希望有机会一对一帮助你实现梦想。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/135064.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MAC设备(M1)环境下编译安装openCV for Java

最近发现一个需求&#xff0c;可以用openCV来实现&#xff0c;碰巧又新买了mac笔记本&#xff0c;就打算利用业余时间安装下openCV。这里将主要步骤记录下&#xff0c;希望能帮助有需要的人。 1、准备编译环境 #查询编译opencv相关依赖 brew info opencv查询结果如下图所示&a…

docker容器中运行jar 出现invalid or corrupt jarfile

1&#xff0c;背景&#xff1a; 在本地java开发完毕之后&#xff0c;想要打包成docker镜像&#xff0c;方便安装。由于本地没有docker环境&#xff0c;也懒得装了。有一台测试的linux机器可以使用&#xff0c;所以先在本地打包生成xxx.jar&#xff0c;然后拷贝到有docker环境的…

openGauss学习笔记-117 openGauss 数据库管理-设置数据库审计-查看审计结果

文章目录 openGauss学习笔记-117 openGauss 数据库管理-设置数据库审计-查看审计结果117.1 前提条件117.2 背景信息117.3 操作步骤 openGauss学习笔记-117 openGauss 数据库管理-设置数据库审计-查看审计结果 117.1 前提条件 审计功能总开关已开启。需要审计的审计项开关已开…

upload-labs-1

文章目录 Pass-01 Pass-01 先上传一个正常的图片&#xff0c;查看返回结果&#xff0c;结果中带有文件上传路径&#xff0c;可以进行利用&#xff1a; 上传一个恶意的webshell&#xff0c;里面写入一句话木马&#xff1a; <?php eval($_POST[cmd]); echo "hello&quo…

【漏洞复现】Apache_HTTP_2.4.50_路径穿越漏洞(CVE-2021-42013)

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证方式一 curl方式二 bp抓捕 1.5、修复建议 说明内容漏洞编号CVE-2021-42013漏洞名称…

【Node.js入门】1.1Node.js 简介

Node.js入门之—1.1Node.js 简介 文章目录 Node.js入门之—1.1Node.js 简介什么是 Node.js错误说法 Node.js 的特点跨平台三方类库自带http服务器非阻塞I/O事件驱动单线程 Node.js 的应用场合适合用Node.js的场合不适合用Node.js的场合弥补Node.js不足的解决方案 什么是 Node.j…

Java连接数据库并查询表中的全部数据

1、导入相关jar包 这里创建简单的maven项目&#xff0c;我们导入相关的jar包 相关依赖&#xff1a; <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependenc…

React进阶之路(一)-- JSX基础、组件基础

文章目录 React介绍React开发环境搭建项目目录说明以及相关调整 JSX基础JSX介绍JSX中使用js表达式JSX列表渲染JSX条件渲染JSX样式处理JSX注意事项 组件基础组件的概念函数组件类组件事件绑定如何绑定事件获取事件对象传递额外参数 组件状态状态不可变表单处理受控表单组件非受控…

menuTreeRef.value?.getCheckedKeys(true) as string[]

问: menuTreeRef.value?.getCheckedKeys(true) as string[]的as string[]什么意思? 回答: 举个例子:

Hive从入门到大牛【Hive 学习笔记】

文章目录 什么是HiveHive的数据存储Hive的系统架构MetastoreHive VS Mysql数据库 VS 数据仓库 Hive安装部署Hive的使用方式命令行方式JDBC方式 Set命令的使用Hive的日志配置Hive中数据库的操作Hive中表的操作 Hive中的数据类型基本数据类型复合数据类型ArrayMapStructStruct和M…

【Leetcode】【每日一题】【简单】2609. 最长平衡子字符串

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/find-the-longest-balanced-subs…

shell的for循环

列表for循环 列表for循环的语法结构如下: for variablein list #每一次循环&#xff0c;依次把列表list 中的一个值赋给循环变量 do #循环体开始的标志commands #循环变量每取一次值&#xff0c;循环体就执行一遍commands done #循环结束的标志&#xff0c;返回循环顶…

PCA9535模块移植

在虚拟机环境里面找到内核文件 更改需要的信息 比如内核设备名称与设备树的名称是否一样 如有需要添加的应用程序 也需要添加进去 根据实际情况来 更改设备名称 还有注意的 比如中断号 根据硬件信息本次中断号为32 所以所有的设备树文件中断号都改为32 现在准备编写驱动文…

TensorFlow学习笔记--(1)张量的随机生成

张量的生成 如何判断一个张量的维数&#xff1a;看张量的中括号有几层 0 1 2 &#xff1a;零维数列 [2 4 6] : 一维向量 [ [1 2 3] [4 5 6] ] : 二维数组 两行三列 第一行数据为 1 2 3 第二行数据为 4 5 6 以此类推 n维张量有n层中括号 tf.zeros(%指定一个张量的维数%) 生成一…

如何将 ONLYOFFICE 文档 7.5 与 Odoo 进行集成

在本教程中&#xff0c;我们将了解如何使用集成应用实现 ONLYOFFICE 文档与 Odoo 之间的连接。 ONLYOFFICE 文档是什么 ONLYOFFICE 文档是一款全面的在线办公工具&#xff0c;提供了文本文档、电子表格和演示文稿的查看和编辑功能。它高度兼容微软 Office 格式&#xff0c;包括…

Oracle-Ogg经典模式升级为集成模式步骤

​前言: Oracle Ogg集成模式比起经典模式功能更加的强大&#xff0c;支持更多的数据类型&#xff0c;压缩表同步&#xff0c;XA事务&#xff0c;多线程模式&#xff0c;PDB模式同步&#xff0c;RAC环境下抽取配置简单等新功能&#xff0c;所以可以选择将经典模式升级转化为集成…

【Qt之QVariant】使用

介绍 QVariant类类似于最常见的Qt数据类型的联合。由于C禁止联合类型包括具有非默认构造函数或析构函数的类型&#xff0c;大多数有趣的Qt类不能在联合中使用。如果没有QVariant&#xff0c;则QObject::property()和数据库操作等将会受到影响。 QVariant对象同时持有一个单一…

基于显著性的无人机多光谱图像语义杂草检测与分类

Saliency-Based Semantic Weeds Detection and Classification Using UAV Multispectral Imaging(2023&#xff09; 摘要1、介绍2、相关工作2.1 监督学习2.2 半监督学习2.3 无监督学习 3、方法3.1 贡献3.2 PC/BC-DIM NEURAL NETWORK&#xff08;预测编码/有偏竞争-分裂输入调制…

【博弈论】混合策略纳什均衡

上一章中遇到了划线法无法找到均衡的情况&#xff0c;例如盖硬币博弈&#xff0c;盖方盖硬币&#xff0c;猜方猜正反。那是因为考虑的都是纯策略&#xff0c;就是每个策略要么选&#xff0c;要么不选。本章考虑混合策略&#xff0c;就是每个策略都有一个选择的概率。 考虑还是这…

xilinx fpga ddr mig axi

硬件 参考&#xff1a; https://zhuanlan.zhihu.com/p/97491454 https://blog.csdn.net/qq_22222449/article/details/106492469 https://zhuanlan.zhihu.com/p/26327347 https://zhuanlan.zhihu.com/p/582524766 包括野火、正点原子的资料 一片内存是 1Gbit 128MByte 16bit …