Echarts+vue电商平台数据可视化——webSocket改造项目

websocket的基本使用,用于测试前端能否正常获取到后台数据

后台代码编写:

const path = require("path");
const fileUtils = require("../utils/file_utils");
const WebSocket = require("ws");
// 创建WebSocket服务端的对象,绑定的端口号是9998
const wss = new WebSocket.Server({port: 9998,
});
// 服务端开启了监听
// 导出一个函数listen
module.exports.listen = () => {// 对客户端的连接事件进行监听// client: 代表的是客户端的连接socket对象wss.on("connection", (client) => {console.log("有客户端连接成功了...");// 对客户端的连接对象进行message事件的监听// msg:由客户端发给服务器的数据client.on("message", async (msg) => {console.log("客户端发送数据给服务器:" + msg);let payload = JSON.parse(msg);const action = payload.action;if (action === "getData") {let filePath = "../data/" + payload.chartName + ".json";// payload.charName; // trend seller map rank hot stockfilePath = path.join(__dirname, filePath);const ret = await fileUtils.getFileJsonData(filePath);// 需要再服务器获取到数据的基础上,增加一个data的字段// data对应的值,就是某个json文件的内容payload.data = ret;client.send(JSON.stringify(payload));} else {// 原封不动的将所有收到的数据转发给每一个处于连接状态的客户端// wss.clients //所有客户端的连接wss.clients.forEach((client) => {client.send(JSON.stringify(payload));});}// 由服务端往客户端发送数据// client.send("hello socket from backend");});});
};

调用的获取文件路径的方法(getFileJsonData):

// 读取文件的工具方法
const fs = require("fs");
module.exports.getFileJsonData = (filePath) => {// 根据文件的路径,读取文件的内容return new Promise((resolve, reject) => {fs.readFile(filePath, "utf-8", (error, data) => {if (error) {// 读取文件失败reject(error);} else {// 读取文件成功// return data; // 这里的return返回的是这个函数的调用者,而不是getFileJsonData这个函数的调用者// 读取文件是一个异步任务,对于一个异步任务,我们也不能通过return的方式来将数据返回给调用者resolve(data);}});});
};

前端使用:

    <button id="connect">连接</button><button id="send" disabled="true">发送数据</button><br />从服务端接收的数据如下: <br /><span id="recv"></span><script>var connect = document.querySelector("#connect");var send = document.querySelector("#send");var recv = document.querySelector("#recv");let ws = null;connect.onclick = function () {ws = new WebSocket("ws://localhost:9998");ws.onopen = () => {console.log("连接服务端成功了...");send.disabled = false;};ws.onclose = () => {console.log("连接服务器失败或关闭");send.disabled = true;};ws.onmessage = (msg) => {console.log("接收从服务器发送过来的数据了");console.log(msg);recv.innerHTML = msg.data;};};send.onclick = function () {ws.send(JSON.stringify({action: "getData",socketType: "trendData",chartName: "trend",value: "",}));ws.send(JSON.stringify({action: "fullScreen",socketType: "fullScreen",chartName: "trend",value: true | false,}));ws.send(JSON.stringify({action: "themeScreen",socketType: "themeScreen",chartName: "",value: "",}));};</script>

 websocket用来改造电商平台项目思维导图:

坐标轴的方向是一个从左往右的方向,朝那个方向就选取x1,y1,x2,y2就选取那几个值

横向:0,0,1,0

竖向:0,0,0,1

报错信息:

js:31[Vue warn]:挂接钩子时出错:“InvalidStateError:在WebSocket上执行send失败:仍处于连接状态。”

代码中的注释解释:

// 有一种报错情况,在组件还没有进行连接成功之前,连接需要一点时间,这个组件就已经进行了加载,就会调用mounted当中指明的send的方法,而send方法是socket_service.js当中定义的一个方法,就会往ws来进行一个send方法的调用,而此时此刻,还没有连接成功

import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
// 引入字体的文件
import "./assets/font/iconfont.css";
// 引入全局的样式文件
import "./assets/css/global.less";
import axios from "axios";
import SocketService from "@/utils/socket_service";
// 对服务端的数据进行连接
// SocketService.Instance().connect(); //这样写会报错,报错说明是Instance是不需要就加上小括号的
// 有一种报错情况,在组件还没有进行连接成功之前,连接需要一点时间,这个组件就已经进行了加载,就会调用mounted当中指明的send的方法,而send方法是socket_service.js当中定义的一个方法,就会往ws来进行一个send方法的调用,而此时此刻,还没有连接成功
SocketService.Instance.connect();
// 其他的组件调用websocket的方式  this.$socket
Vue.prototype.$socket = SocketService.Instance;
// 请求的基准路径的配置
axios.defaults.baseURL = "http://127.0.0.1:8888/api/";
// 将axios挂载到Vue的原型对象上
// 在别的组件中 this.$http
Vue.prototype.$http = axios;// 将全局的echarts对象挂载到Vue的原型对象中
// 别的组件中this.$echarts
Vue.prototype.$echarts = window.echarts;Vue.config.productionTip = false;new Vue({router,store,render: (h) => h(App),
}).$mount("#app");

解决方法,添加一个连接标识,判断websocket连接成功还是失败,true连接成功,false连接失败

项目改造后的后台编写:

export default class SocketService {// 单例static instance = null;static get Instance() {if (!this.instance) {this.instance = new SocketService();}return this.instance;}// 和服务器连接的socket对象ws = null;// 怎么在得到数据之后,将每个图表数据传递给每个图表组件,让图表数据可以得到更新// 先将每一个图表组件的某一个方法先存储在我们当前的这个模块中,比如一个实例属性中,一旦得到有服务端给我们的数据之后,在调用我们之前所存储起来的那个方法,就可以将数据传递给每个图表组件// 存储回调函数callBackMapping = {};// 标识是否连接成功connected = false;// 记录重试的次数sendRetryCount = 0;// 重新连接尝试的次数connectRetryCount = 0;// 定义连接服务器的方法connect() {// 连接服务器if (!window.WebSocket) {return console.log("您的浏览器不支持WebSocket");}this.ws = new WebSocket("ws://localhost:9998");// 连接成功的事件this.ws.onopen = () => {console.log("连接服务器成功了");this.connected = true;// 重置重新连接的次数this.connectRetryCount = 0;};// 1.连接服务器失败// 2.当连接成功之后,服务器关闭的情况this.ws.onclose = () => {console.log("连接服务器失败");// 标识是否连接成功,没有连接成功this.connected = false;this.connectRetryCount++;// 这个时候应该进行重新连接的尝试,但是每一次连接失败,下一次的连接都是500毫秒 不太合适,因为尝试的越多,可能服务器已经坏了,或者已经关闭了,就没有必要那么频繁的次数来进行重新连接的尝试setTimeout(() => {this.connect();}, 500 * this.connectRetryCount);};this.ws.onmessage = (msg) => {console.log("从服务器获取了数据");// 真正服务端发送过来的原始数据时在msg中的data字段// 如果在的得到数据之后把数据传递给每个图表组件会好一些,因为只有图表组件需要数据console.log(msg.data, msg, "--\\\\");const recvData = JSON.parse(msg.data);const socketType = recvData.socketType;// 判断回调函数是否存在if (this.callBackMapping[socketType]) {const action = recvData.action;if (action === "getData") {const realData = JSON.parse(recvData.data);this.callBackMapping[socketType].call(this, realData);} else if (action === "fullScreen") {this.callBackMapping[socketType].call(this, recvData);} else if (action === "themeScreen") {this.callBackMapping[socketType].call(this, recvData);}}};}// 下面的这个三个方法需要通过组件来调用// 回调函数的注册// socketType  这个函数的唯一标识,callBack这个函数的回调函数registerCallBack(socketType, callBack) {this.callBackMapping[socketType] = callBack;}// 取消某一个回调函数// socketType 这个函数的唯一标识unRegisterCallBack(socketType) {this.callBackMapping[socketType] = null;}// 发送数据的方法send(data) {// 判断此时此刻有没有连接成功if (this.connected) {this.sendRetryCount = 0;this.ws.send(JSON.stringify(data));} else {this.sendRetryCount++;setTimeout(() => {this.send(data);}, this.sendRetryCount * 500);}// this.ws.send(JSON.stringify(data));}
}

新旧setOption是一个相互整合,相互覆盖的过程

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

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

相关文章

jenkins修改端口以及开机自启

修改Jenkins端口 方式一&#xff1a;通过配置文件修改&#xff08;以CentOS为例&#xff09; 找到配置文件&#xff1a;在CentOS系统中&#xff0c;通常可以在/etc/sysconfig/jenkins文件中修改Jenkins的配置。如果没有这个文件&#xff0c;也可以查看/etc/default/jenkins&…

《Vue3实战教程》34:Vue3状态管理

如果您有疑问&#xff0c;请观看视频教程《Vue3实战教程》 状态管理​ 什么是状态管理&#xff1f;​ 理论上来说&#xff0c;每一个 Vue 组件实例都已经在“管理”它自己的响应式状态了。我们以一个简单的计数器组件为例&#xff1a; vue <script setup> import { r…

jQuery Mobile 可折叠块

jQuery Mobile 可折叠块 1. 引言 在构建移动端网站时&#xff0c;有效地使用屏幕空间是至关重要的。jQuery Mobile 是一个流行的框架&#xff0c;它通过提供丰富的UI组件来帮助开发者创建响应式的移动应用。在这些组件中&#xff0c;可折叠块&#xff08;Collapsible Blocks&…

简单使用linux

1.1 Linux的组成 Linux 内核&#xff1a;内核是系统的核心&#xff0c;是运行程序和管理 像磁盘和打印机等硬件设备的核心程序。 文件系统 : 文件存放在磁盘等存储设备上的组织方法。 Linux 能支持多种目前浒的文件系统&#xff0c;如 ext4 、 FAT 、 VFAT 、 ISO9660 、 NF…

微服务のGeteWay

目录 概念&#xff1a; 三大核心&#xff1a; 工作流程&#xff1a; 9527网关如何做路由映射&#xff1a; GetWay高级特性&#xff1a; 按服务名动态路由服务&#xff1a; 断言Route Predicate Factories &#xff1a; 获取当前时区时间&#xff1a; After Route &…

Python世界:函数模块知识点小结

Python世界&#xff1a;函数模块知识点小结 Python函数模块 部分笔记汇总&#xff0c;持续刷新中。区别于其他笔记之处在于&#xff0c;主要记录易错点坑点。 Python函数模块 函数是编码过程中最小的功能模块。 什么是函数式编程&#xff1f; 函数式编程&#xff0c;本质是通…

机器学习随机森林回归时间序列预模型中时间滑动窗口作用以及参数设置

一、时间序列模型中时间滑动窗口作用 在时间序列模型中&#xff0c;时间滑动窗口&#xff08;Sliding Window&#xff09;起到了至关重要的作用。它是一种常见且有效的数据表示技术&#xff0c;通过将时间序列数据分割成多个固定大小的窗口&#xff0c;来捕捉和分析数据中的模式…

idea 的 springboot项目spring-boot-devtools 自动编译 配置热部署

1&#xff0c;设置一 2&#xff0c;设置二 设置二&#xff08;旧版本&#xff09; CtrlShiftAlt/ 点击弹出框中Registry... 引入&#xff08;如果报错&#xff0c;换不同的版本&#xff09; <dependency><groupId>org.springframework.boot</groupId><a…

GitHub CLI 安装指南

GitHub CLI 是 GitHub 官方提供的命令行工具&#xff0c;可以帮助开发者方便地与 GitHub 平台进行交互&#xff0c;例如克隆仓库、提交代码、创建 Pull Request 等。 相比传统的 HTTPS 下载和操作&#xff0c;GitHub CLI 提供了以下显著的优势和特殊功能&#xff1a; GitHub …

建立一个Macos载入image的实例含界面

前言 为了方便ios程序的开发&#xff0c;有时候需要先用的Macos平台进行一些功能性的程序开发。 作为对比和参考。 1、创建一个MacOS的App 2、主界面控件的增加 添加的控件方法与ios相同&#xff0c;也是再用commandshiftL&#xff08;CtrlShiftL&#xff09;,就会弹出控件…

Megatron - LM 怎么进行模型切分的,怎么匹配服务器的

Megatron - LM 怎么进行模型切分的,怎么匹配服务器的? Megatron - LM主要针对Transformer模型进行层内模型并行训练,其模型切分和服务器匹配策略如下: 模型切分 多头注意力模块切分:在Transformer的多头注意力模块中,Megatron - LM利用其内在并行性,将与矩阵乘运算相关…

在CodeBlocks搭建SDL2工程构建TFT彩屏模拟器虚拟TFT彩屏幕显示

在CodeBlocks搭建SDL2工程构建TFT彩屏模拟器虚拟TFT彩屏幕显示 参考文章源码下载地址一、SDL2的创建、初始化、退出二、系统基本Tick、彩屏刷新、按键事件三、彩屏获取与设置颜色四、彩屏填充颜色及清屏五、彩屏显示中文和英文字符串六、彩屏显示数字七、彩屏初始化八、主函数测…

基于Springboot + vue实现的校园周边美食探索及分享平台

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

LeetCode - 初级算法 数组(删除排序数组中的重复项)

免责声明:本文来源于个人知识与公开资料,仅用于学术交流。 删除排序数组中的重复项 这篇文章讨论如何从一个非严格递增的数组 nums 中删除重复的元素,使每个元素只出现一次,并返回新数组的长度。因为数组是排序的,只要是相同的肯定是挨着的,所以我们需要遍历所有数组,然…

MySQL深度解析:优化策略与实战案例

MySQL深度解析:优化策略与实战案例 在当今数据驱动的时代,数据库作为数据存储与管理的核心组件,其性能的优化直接关系到业务系统的响应速度、稳定性和可扩展性。MySQL,作为一款开源的关系型数据库管理系统,凭借其高性能、高可靠性和易用性,在Web应用、数据分析等领域得到…

MVCC实现原理以及解决脏读、不可重复读、幻读问题

MVCC实现原理以及解决脏读、不可重复读、幻读问题 MVCC是什么&#xff1f;有什么作用&#xff1f;MVCC的实现原理行隐藏的字段undo log日志版本链Read View MVCC在RC下避免脏读MVCC在RC造成不可重复读、丢失修改MVCC在RR下解决不可重复读问题RR下仍然存在幻读的问题 MVCC是什么…

【leetcode100】二叉树的中序遍历

1、题目描述 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2] 2、初始思路 2.1 思路 中序遍历的顺序是左→根→右&#xff0c;定义一个函数进行遍历 # Definition for …

租用服务器还是服务器托管:哪种方案更适合您?

随着企业对网络服务质量要求的不断提高&#xff0c;租用服务器和服务器托管是两种常见的选择&#xff0c;各自具备独特的优势和适用场景。这篇文章将从多个维度对这两种方案进行详细分析&#xff0c;帮助大家进行对比选择。 租用服务器的优劣势分析 优点 无需大额初始投入 租用…

Quartus In-System Sources and Probes Editor 的使用说明

文章目录 前言使用说明参考资料 前言 Quartus 提供了 In-System Sources and Probes Editor 调试工具&#xff0c;通过 JTAG 接口使用该工具可以驱动和采样内部节点的逻辑值。即通过 Sources 功能来驱动 FPGA 内部信号&#xff0c;通过 Probes 功能来探测内部节点的逻辑值。在…

2. C语言 基础语法

本章目录: 前言1. C 语言的基础结构1.1 C 程序的基本构成1.2 一个简单的 C 程序实例1.3 复杂的 C 程序结构 2. C 语言的基本构成单元2.1 关键字标准关键字C99 新增关键字C11 新增关键字 2.2 标识符2.3 常量2.4 注释 3. 语句与表达式3.1 语句3.2 表达式 4. 分隔符与空格4.1 分隔…