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 stock
        filePath = 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是一个相互整合,相互覆盖的过程

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Transformer从零详细解读——DASOU讲AI

1. 从全局角度概括Transformer transformer的任务是什么&#xff1f; 进一步细化 进一步细化&#xff0c;注意&#xff1a;每个encoder结构相同&#xff0c;参数不同&#xff1b;decoder同理 原论文中的图如下&#xff1a; 2.Encoder 2.1 输入部分 &#xff08;1&#xff09…

696: Soldiers

曼哈顿距离&#xff08;Manhattan Distance&#xff09; 在二维空间中&#xff0c;两个点 (x1, y1) 和 (x2, y2) 的 曼哈顿距离 是&#xff1a; |x1 - x2| |y1 - y2| 曼哈顿距离描述了在网格上行走的距离&#xff0c;限制只能水平或垂直移动。 #include <iostream>…

自学记录鸿蒙API 13:实现多目标识别Object Detection

起步&#xff1a;什么叫多目标识别&#xff1f; 无论是生活中的动物识别、智能相册中的场景分类&#xff0c;还是工业领域的检测任务&#xff0c;都能看到多目标识别的身影。这次&#xff0c;我决定通过学习HarmonyOS最新的Object Detection API&#xff08;API 13&#xff09…

【Cesium】九、Cesium点击地图获取点击位置的坐标,并在地图上添加图标

文章目录 一、前言二、实现方法三、App.vue 一、前言 查找发现好几种方法可以获取到点击位置的坐标。这里我实现需求就不深究学习了。将几位大佬的方法学习过来稍微整合了一下。 本文参考文章&#xff1a; cesium 4种拾取坐标的方法 【Cesium基础学习】拾取坐标 cesium拾取当…

ts总结一下

ts基础应用 /*** 泛型工具类型*/ interface IProps {id: string;title: string;children: number[]; } type omita Omit<IProps, id | title>; const omitaA: omita {children: [1] }; type picka Pick<IProps, id | title>; const pickaA: picka {id: ,title…

人脑处理信息的速度与效率:超越计算机的直观判断能力

人脑处理信息的速度与效率&#xff1a;超越计算机的直观判断能力 关键词&#xff1a; #人脑信息处理 Human Brain Information Processing #并行处理 Parallel Processing #视觉信息分析 Visual Information Analysis #决策速度 Decision Speed #计算机与人脑比较 Computer v…

CentOS — 目录管理

文章目录 一、目录结构二、切换目录三、查看目录四、创建目录五、复制目录六、剪切目录七、删除目录 目录也是一种文件。 蓝色目录&#xff0c;绿色可执行文件&#xff0c;红色压缩文件&#xff0c;浅蓝色链接文件&#xff0c;灰色其它文件&#xff0c; 点开头的是隐藏文件&…

cursor设备ID修改器,你可以无限试用cursor了!

文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons&#xff1a;JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram&#xff0c;自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 &#xff1f; 5 IDEA必装的插件&…

springboot523基于Spring Boot的大学校园生活信息平台的设计与实现(论文+源码)_kaic

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本大学校园生活信息平台就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据…

RabbitMQ中的异步Confirm模式:提升消息可靠性的利器

在现代分布式系统中&#xff0c;消息队列&#xff08;Message Queue&#xff09;扮演着至关重要的角色&#xff0c;它能够解耦系统组件、提高系统的可扩展性和可靠性。RabbitMQ作为一款广泛使用的消息队列中间件&#xff0c;提供了多种机制来确保消息的可靠传递。其中&#xff…

集线器,交换机,路由器,mac地址和ip地址知识记录总结

一篇很不错的视频简介 基本功能 从使用方面来说&#xff0c;都是为了网络传输的标识&#xff0c;和机器确定访问对象 集线器、交换机和路由器 常听到路由器和集线器&#xff0c;下面是区别&#xff1a; 集线器 集线器&#xff1a;一个简单的物理扩展接口数量的物理硬件。…

什么是 GPT?Transformer 工作原理的动画展示

大家读完觉得有意义记得关注和点赞&#xff01;&#xff01;&#xff01; 目录 1 图解 “Generative Pre-trained Transformer”&#xff08;GPT&#xff09; 1.1 Generative&#xff1a;生成式 1.1.1 可视化 1.1.2 生成式 vs. 判别式&#xff08;译注&#xff09; 1.2 Pr…

u3d中JSON数据处理

一.认识JSON 1.1 Json概述 JSON&#xff08;JavaScript Object Notation&#xff0c;JavaScript对象表示法&#xff09;JSON和XML是比较类似的技术&#xff0c;都是用来存储文本信息数据的&#xff1b;相对而言&#xff0c;JSON比XML体积更小巧&#xff0c;但是易读性不如XML…

Android 模拟器系统镜像选择指南

Android 模拟器系统镜像选择指南 在选择 Android 模拟器的系统镜像时&#xff0c;根据实际需求选择合适的版本。以下是具体建议&#xff1a; 1. 目标 API Level 如果需要适配最新版本的 Android&#xff1a; 选择&#xff1a;API 35 (Android 14)&#xff08;代号&#xff1…

网络分析工具-tcpdump

文章目录 前言一、tcpdump基础官网链接命令选项详解常规过滤规则tcpdump输出 一、tcpdump实践HTTP协议ICMP状态抓包 前言 当遇到网络疑难问题的时候&#xff0c;抓包是最基本的技能&#xff0c;通过抓包才能看到网络底层的问题 一、tcpdump基础 tcpdump是一个常用的网络分析工…

打造三甲医院人工智能矩阵新引擎(一):文本大模型篇--基于GPT-4o的探索

一、引言 当今时代&#xff0c;人工智能技术正以前所未有的速度蓬勃发展&#xff0c;深刻且广泛地渗透至各个领域&#xff0c;医疗行业更是这场变革的前沿阵地。在人口老龄化加剧、慢性疾病患病率上升以及人们对健康需求日益增长的大背景下&#xff0c;三甲医院作为医疗体系的核…

mysql连接时报错1130-Host ‘hostname‘ is not allowed to connect to this MySQL server

不在mysql服务器上通过ip连接服务提示1130错误怎么回事呢。这个错误是因为在数据库服务器中的mysql数据库中的user的表中没有权限。 解决方案 查询mysql库的user表指定账户的连接方式 SELECT user, host FROM mysql.user;修改指定账户的host连接方式 update mysql.user se…

linux下安装达梦数据库v8详解

目录 操作系统、数据库 1、下载达梦数据库 2、安装前准备 2.1、建立数据库用户和组 2.2、修改文件打开最大数 2.3、挂载镜像 2.4、新建安装目录 3、数据库安装 4、配置环境变量 5、初始化数据库实例 6、注册服务 7、使用数据库 8、卸载数据库 9、多实例管理 10、…

低代码引擎插件开发:开启开发的便捷与创新之路

OneCode授权演示 一、低代码引擎与插件开发的概述 在当今快节奏的软件开发领域&#xff0c;低代码引擎正逐渐崭露头角。低代码引擎旨在让开发人员能够以最少的代码量创建功能丰富的应用程序&#xff0c;而其中的关键组成部分便是插件开发。低代码引擎通过提供可视化的开发环境…

多光谱图像的处理和分析方法有哪些?

一、预处理方法 1、辐射校正&#xff1a; 目的&#xff1a;消除或减少传感器本身、大气条件以及太阳光照等因素对多光谱图像辐射亮度值的影响&#xff0c;使得图像的辐射值能够真实反映地物的反射或发射特性。 方法&#xff1a;包括传感器校正和大气校正。传感器校正主要是根…