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.rhkb.cn/news/501093.html

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

相关文章

【数据结构】双向循环链表的使用

双向循环链表的使用 1.双向循环链表节点设计2.初始化双向循环链表-->定义结构体变量 创建头节点&#xff08;1&#xff09;示例代码&#xff1a;&#xff08;2&#xff09;图示 3.双向循环链表节点头插&#xff08;1&#xff09;示例代码&#xff1a;&#xff08;2&#xff…

【深度学习】卷积网络代码实战ResNet

ResNet (Residual Network) 是由微软研究院的何凯明等人在2015年提出的一种深度卷积神经网络结构。ResNet的设计目标是解决深层网络训练中的梯度消失和梯度爆炸问题&#xff0c;进一步提高网络的表现。下面是一个ResNet模型实现&#xff0c;使用PyTorch框架来展示如何实现基本的…

【51项目】51单片机自制小霸王游戏机

视频演示效果&#xff1a; 纳新作品——小霸王游戏机 目录&#xff1a; 目录 视频演示效果&#xff1a; 目录&#xff1a; 前言&#xff1a; 一、连接方式&#xff1a; 1.1 控制引脚 1.2. 显示模块 1.3. 定时器 1.4. 游戏逻辑与硬件结合 1.5. 中断处理 二、源码分析&#xff1a…

2024/12/29 黄冈师范学院计算机学院网络工程《路由期末复习作业一》

一、选择题 1.某公司为其一些远程小站点预留了网段 172.29.100.0/26&#xff0c;每一个站点有10个IP设备接到网络&#xff0c;下面那个VLSM掩码能够为该需求提供最小数量的主机数目 &#xff08; &#xff09; A./27 B./28 C./29 D./30 -首先审题我们需要搞清楚站点与网…

【OpenCV】使用Python和OpenCV实现火焰检测

1、 项目源码和结构&#xff08;转&#xff09; https://github.com/mushfiq1998/fire-detection-python-opencv 2、 运行环境 # 安装playsound&#xff1a;用于播放报警声音 pip install playsound # 安装opencv-python&#xff1a;cv2用于图像和视频处理&#xff0c;特别是…

Vue2: table加载树形数据的踩坑记录

table中需要加载树形数据,如图: 官网给了两个例子,且每个例子中的tree-props都是这么写的: :tree-props="{children: children, hasChildren: hasChildren}" 给我一种错觉,以为数据结构中要同时指定children和hasChildren字段,然而,在非懒加载模式下,数据结…

深度学习模型预测值集中在某一个值

深度学习模型&#xff0c;训练过程中&#xff0c;经常遇到预测的结果集中在某个值&#xff0c;而且在学习的过程中会变&#xff0c;样例如下。 主要有如下解决方案 1、更换relu ->tanh 或者其他激活函数 2、更改随机种子&#xff0c;估计是没有初始化好&#xff0c;或者调…

图书项目:整合SSM

步骤&#xff1a; pom文件&#xff1a;导包&#xff0c;写入静态资源导出配置&#xff0c;连接数据库 建包&#xff1a;controller dao/mapper pojo service 配置文件&#xff1a;mybatis-config.xml applicationContext.xml&#xff08;Spring的配置文件&#xff09; datab…

javacript中function (res) {}与箭头函数表达式(res) =>{}的区别

javacript中function (res) {}与(res) &#xff1e;{}的区别 function (res) {} 代码演示 let shape {name:长方形,say:function(){console.log(我是this.name)setTimeout(function(){console.log(3秒后输出我是: this.name); //this.name为undefined}, 3000)} }shape.sa…

Docker安装(Docker Engine安装)

一、Docker Engine和Desktop区别 Docker Engine 核心组件&#xff1a;Docker Engine是Docker的核心运行时引擎&#xff0c;负责构建、运行和管理容器。它包括守护进程&#xff08;dockerd&#xff09;、API和命令行工具客户端&#xff08;docker&#xff09;。适用环境&#…

【卡通风格的的登录界面】

卡通风格的的登录、注册界面模板&#xff0c;使用uni-app编写&#xff0c;直接复制粘贴即可。 废话不多说&#xff0c;代码如下&#xff1a; login.vue文件 <template><view class"content"><view class"login-form"><view class&quo…

【AI】最近有款毛茸茸AI生成图片圈粉了,博主也尝试使用风格转换生成可爱的小兔子,一起来探索下是如何实现的

应用名称&#xff1a;一键变身毛茸茸小兔子 体验地址&#xff1a;点击跳转体验 模型名称&#xff1a;Kolors&#xff0c;点击跳转 背景 Gitee AI最近发起了一个社群挑战赛。 如果最近你也没什么好点子&#xff0c;想练习又无从下手&#xff0c;怎么办呢&#xff1f; 没关系&a…

重学 Android 自定义 View 系列(十):带指针的渐变环形进度条

前言 该篇文章根据前面 重学 Android 自定义 View 系列(六)&#xff1a;环形进度条 拓展而来。 最终效果如下&#xff1a; 1. 扩展功能 支持进度顺时针或逆时针显示在进度条末尾添加自定义指针图片使用线性渐变为进度条添加颜色效果 2. 关键技术点解析 2.1 进度方向控制的…

Oracle 23ai 图形界面安装

新年的第一篇博客&#xff0c;展示下Oracle 23ai的图形化安装。 主要给大家看下界面&#xff0c;安装的过程与19c没什么不同。 安装前 安装Oracle Database Preinstallation RPM&#xff1a; sudo dnf install oracle-database-preinstall-23aioracle用户有了&#xff1a; …

跳转至系统设置下某个子模块 - 鸿蒙 Harmony

有时候遇到一些需要预授权系统权限才可访问的功能,可以通过如下方式先跳转至系统设置下的某个子页面进行配置,具体如下 code 所示参考: 具体跳转到设置的子设置页面如下也有注释,可供参考使用 /*** 访问系统设置: 子目录* */ static accessSystemSettingSubDirectory(uriKey?:…

el-table 实现纵向多级表头

为了实现上图效果&#xff0c;最开始打算用el-row、el-col去实现&#xff0c;但发现把表头和数据分成两大列时&#xff0c;数据太多时会导致所在格高度变高。但由于每一格数据肯定不一样&#xff0c;为保持高度样式一致&#xff0c;就需要我们手动去获取最高格的高度之后再设置…

2024年度总结答疑

大家好&#xff0c;我是大师兄。在2024年的最后一天&#xff0c;让我们一起来复盘总结&#xff0c;回顾我们在学习和工作中的能力提升、经验教训以及如何在未来做得更好。 过去一年&#xff0c;我们努力提升了学习和工作能力&#xff0c;学习了新的技术和知识&#xff0c;积极参…

flutter组件————Row和Column

Row和Column 在Flutter中&#xff0c;Row 和 Column 是两个非常常用的布局组件&#xff0c;它们用于按照水平或垂直方向排列子组件。 Row Row 组件是一个将子组件沿水平方向&#xff08;从左到右&#xff09;排列的控件。它通常用于创建一行中的多个小部件&#xff0c;比如文…

苹果解锁工具iToolab UnlockGo 中文安装版(附教程+补丁) 2024年6月ios17.4.1可用(记得点赞)解压密码请看文章!!! 评论区获取最新链接

UnlockGo 允许您非常轻松地绕过 iPhone 的密码并获得对设备的完全访问权限。它在以下场景中很有用。 在几分钟内删除 iPhone/iPad 上的各种锁定。 解锁 4 位/6 位密码、Touch ID 和 Face ID 删除没有密码的 iCloud 免费锁 无需密码即可从 iPhone/iPad/iPod 中删除 Apple ID…

[最佳方法] 如何将视频从 Android 发送到 iPhone

概括 将大视频从 Android 发送到 iPhone 或将批量视频从 iPhone 传输到 Android 并不是一件容易的事情。也许您已经尝试了很多关于如何将视频从 Android 发送到 iPhone 15/14 的方法&#xff0c;但都没有效果。但现在&#xff0c;通过本文中的这 6 种强大方法&#xff0c;您可…