iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >Web Worker线程electron问题怎么解决
  • 134
分享到

Web Worker线程electron问题怎么解决

2023-07-04 13:07:16 134人浏览 独家记忆
摘要

本文小编为大家详细介绍“WEB Worker线程electron问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“Web Worker线程electron问题怎么解决”文章能帮助大家解决疑惑,下面跟着小编的思路

本文小编为大家详细介绍“WEB Worker线程electron问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“Web Worker线程electron问题怎么解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

    初始化项目

    electron 开发时会遇到一对多的情况,在进行 websocket 通信时,如果接收到服务端多个指令时,而这个指令刚好需要占用线程,这个时候整个界面就会失去响应,那么我们就可以使用线程来解决这个问题.

    npm create vite@latest electron-worker

    执行完后修改 package.JSON 如下:

    {  "name": "electron-worker",  "private": true,  "version": "0.0.0",  "scripts": {    "dev": "vite",    "build": "vite build",    "preview": "vite preview"  },  "dependencies": {},  "devDependencies": {    "@vitejs/plugin-Vue": "^3.2.0",    "vite": "^3.2.0",    "vue": "^3.2.41",    "electron": "19.1.4",    "electron-builder": "^23.3.3"  }}

    编写入口文件和 electron 插件

    创建 mainEntry.js 作为 electron 的入口文件,启动一个窗口

    // src/main/mainEntry.jsimport { app, BrowserWindow } from "electron";process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = "true";let mainWindow;app.whenReady().then(() => {  let config = {    webPreferences: {      nodeIntegration: true,      webSecurity: false,      allowRunningInsecureContent: true,      contextIsolation: false,      webviewTag: true,      spellcheck: false,      disablehtmlFullscreenWindowResize: true,    },  };  mainWindow = new BrowserWindow(config);  mainWindow.webContents.openDevTools({ mode: "undocked" });  mainWindow.loadURL(process.argv[2]);});

    编写 vite 插件,在服务器启动后加载 electron 入口文件

    // plugins/devPlugin.jsexport const devPlugin = () => {  return {    name: "dev-plugin",    configureServer(server) {      require("esbuild").buildSync({        entryPoints: ["./src/main/mainEntry.js"],        bundle: true,        platfORM: "node",        outfile: "./dist/mainEntry.js",        external: ["electron"],      });      server.httpserver.once("listening", () => {        let { spawn } = require("child_process");        let electronProcess = spawn(require("electron").toString(), ["./dist/mainEntry.js", `Http://127.0.0.1:${server.config.server.port}/`], {          cwd: process.cwd(),          stdio: "inherit",        });        electronProcess.on("close", () => {          server.close();          process.exit();        });      });    },  };};

    使用插件

    import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'import { devPlugin } from "./plugins/devPlugin";export default defineConfig({  plugins: [devPlugin(), vue()],})

    将 vue 项目文件放入和 main 同级, 结构如下所示

    └─src     ├─main    │      mainEntry.js      └─renderer        │  App.vue        │  main.js        ├─assets        └─components

    修改 index.html

    <!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8" />    <link rel="icon" type="image/svg+xml" href="/vite.svg" rel="external nofollow"  />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <title>Vite + Vue</title>  </head>  <body>    <div id="app"></div>    <script type="module" src="/src/renderer/main.js"></script>  </body></html>

    现在执行 npm run dev 就可以运行项目了

    webSocket

    websocket 服务

    var WebSocketServer = require('ws').Server;var wss = new WebSocketServer({port: 8181});wss.on('connection', function (ws) {  console.log('有客户端连接');  ws.send("连接成功")  ws.on('message', function (jsonStr) {    console.log(jsonStr.toString());  });});

    连接 websocket 服务

    准备 Socket 对象

    export default class Socket {  websocket  wsUrl  constructor(wsUrl) {    this.wsUrl = wsUrl  }  init() {    if (this.websocket) return this.websocket    const socket = this.websocket = new WebSocket(this.wsUrl)    // WebSocket 接收服务端数据    socket.onmessage = (e) => {      console.log("接收服务端消息:", e.data)    }    // WebSocket 断开连接后触发    socket.onclose = (e) => {}    // WebSocket 连接成功    socket.onopen = () => {      console.log("连接成功")    }    // WebSocket 连接异常    socket.onerror = (e) => {}  }}

    连接 Socket

    <script setup>import Socket from './socket'const socket = new Socket("ws://localhost:8181")function reGISter() {  socket.init()}</script><template>  <div>    <button @click="register">注册</button>  </div></template><style scoped></style>

    点击注册后显示如下:

    Web Worker线程electron问题怎么解决

    发送心跳

    一般为了确保服务一直连接,需要客户端定时给服务发送心跳

    export default class Socket {  // ...  heartbeatCount // 心跳次数  heartbeatTimer // 心跳定时器  heartbeatInterval = 1000 * 20 // 心跳发送频率(2秒一次)  // ...  sendHeartBeat() {    this.heartbeatCount = 0    if (this.heartbeatTimer) clearInterval(this.heartbeatTimer)    this.heartbeatTimer = setInterval(() => {      this.websocket.send("发送心跳")    }, this.heartbeatInterval)  }}

    App.vue

    function sendHeartBeat() {  socket.sendHeartBeat()}
    <button @click="sendHeartBeat">发送心跳</button>

    Web Worker线程electron问题怎么解决

    可以看到我们在服务端日志里看到有持续心跳日志

    取消心跳

    因为是定时器发送,当服务端掉线后定时器却还在继续发送,现在我们来优化这个

    // 断开连接onclose() {  console.log("已断开连接")  this.websocket = null  // 清除心跳定时器  if (this.heartbeatTimer) clearInterval(this.heartbeatTimer)}

    在 socket 断开后进行调用

    // WebSocket 断开连接后触发socket.onclose = (e) => {  this.onclose()}

    重新连接

    websocket 断开有可能是客户端网络问题,所以我们需要进行尝试重连

    export default class Socket {  // ...  socketOpen // 是否连接  isReconnect = true // 是否可以重新连接  reconnectCountMax = 3 // 最大重新次数  reconnectTimer // 重连定时器  reconnectCurrent = 0  // 重连次数  reconnectInterval // 1000 * 3 // 重连频率(3秒一次)  // ...  // 断开连接  onclose() {    console.log("已断开连接")    this.websocket = null    // 清除心跳定时器    if (this.heartbeatTimer) clearInterval(this.heartbeatTimer)    // 需要重新连接    if (this.isReconnect) {      this.reconnectTimer = setTimeout(() => {        if (this.reconnectCurrent >= this.reconnectCountMax) {          console.log("超过重连次数,重连失败")          clearTimeout(this.reconnectTimer)        } else {          this.reconnectCurrent += 1          this.reconnect()        }      }, this.reconnectInterval)    }  }  // 重新连接  reconnect() {    console.log("重新连接", this.reconnectCurrent)    if (this.websocket && this.socketOpen) {      this.websocket.close()    }    this.init()  }}

    我们每三秒一次进行尝试重新连接,如果重连三次还未连接,那我们认为无法重新连接

    其它优化

    export enum PostMessageType {  ON_OPEN = 'open', // websocket开启  ON_ERROR = 'error', // websocket异常  ON_CLOSE = 'close', // websocket关闭  ON_MESSAGE = 'message', // websocket接收消息  RECONNECT = 'reconnect', // websocket重新连接  HEARTBEAT = 'heartbeat', // websocket发送心跳  OFF = 'off', // websocket主动关闭  REGISTER = 'register', // websocket注册成功}
    class Socket {  wsUrl: string // 服务地址  websocket: WebSocket | null = null // websocket对象  socketOpen: boolean = false // socket是否开启  heartbeatTimer: any // 心跳定时器  heartbeatCount: number = 0 // 心跳次数  heartbeatInterval: number = 1000 * 20 // 心跳发送频率(2秒一次)  isReconnect: boolean = true // 是否可以重新连接  reconnectCountMax: number = 3 // 最大重新次数  reconnectCurrent: number = 0 // 已发起重连次数  reconnectTimer: any // 重连timer  reconnectInterval: number = 1000 * 3 // 重连频率(3秒一次)  constructor(url: string) {    this.wsUrl = url  }  // socket 初始化  init() {    if (this.websocket) return this.websocket    const socket = this.websocket = new WebSocket(this.wsUrl)    // WebSocket 接收服务端数据    socket.onmessage = (e) => {      this.receive(e.data)    }    // WebSocket 断开连接后触发    socket.onclose = (e) => {      this.postMessage(PostMessageType.ON_CLOSE, e)      this.onclose()    }    // WebSocket 连接成功    socket.onopen = () => {      this.onopen()    }    // WebSocket 连接异常    socket.onerror = (e) => {      this.postMessage(PostMessageType.ON_ERROR, e)    }  }  // 连接成功后的回调  onopen() {    this.socketOpen = true    this.isReconnect = true    this.reconnectCurrent = 1    this.heartbeatCount = 0    this.postMessage(PostMessageType.ON_OPEN)  }    postMessage(type: PostMessageType, data?: any) {}    onclose() {    this.websocket = null    this.socketOpen = false    // 清除心跳定时器    clearInterval(this.heartbeatTimer)    // 需要重新连接    if (this.isReconnect) {      this.reconnectTimer = setTimeout(() => {        if (this.reconnectCurrent >= this.reconnectCountMax) {          clearTimeout(this.reconnectTimer)        } else {          this.reconnectCurrent += 1          this.reconnect()        }      }, this.reconnectInterval)    }  }    reconnect() {    this.postMessage(PostMessageType.RECONNECT, this.reconnectCurrent)    if (this.websocket && this.socketOpen) {      this.websocket.close()    }    this.init()  }    send(data: any, callback?: () => void) {    const ws = this.websocket    if (!ws) {      this.init()      setTimeout(() => {        this.send(data, callback)      }, 1000)      return    }    switch (ws.readyState) {      case ws.OPEN:        ws.send(data)        if (callback) {          callback()        }        break      case ws.CONNECTING:        // 未开启,则等待1s后重新调用        setTimeout(() => {          this.send(data, callback)        }, 1000)        break      default:        this.init()        setTimeout(() => {          this.send(data, callback)        }, 1000)    }  }  receive(data: any) {    this.postMessage(PostMessageType.ON_MESSAGE, data)  }    sendHeartBeat(data: any) {    this.heartbeatCount = 0    if (this.heartbeatTimer) clearInterval(this.heartbeatTimer)    this.heartbeatTimer = setInterval(() => {      this.send(data, () => {        this.heartbeatCount += 1        this.postMessage(PostMessageType.HEARTBEAT, { heartBeatData: data, heartbeatCount: this.heartbeatCount })      })    }, this.heartbeatInterval)  }    close() {    this.isReconnect = false    this.postMessage(PostMessageType.OFF, "主动断开websocket连接")    this.websocket && this.websocket.close()  }}

    上面是基础的 websocket ,具体使用需要结合业务进行继承使用

    export default class SelfSocket extends Socket {  registerData: any // 注册数据  heartBeatData: any // 心跳数据  constructor(url: string) {    super(url);  }  initSocket(registerData: any, heartBeatData: any) {    this.registerData = registerData    this.heartBeatData = heartBeatData    super.init()  }  onopen() {    this.register()    super.onopen();  }    register() {    this.send(this.registerData, () => {      this.sendHeartBeat(this.heartBeatData)      this.postMessage(PostMessageType.REGISTER, this.registerData)    })  }  send(data: any, callback?: () => void) {    // 数据加密    const str = _encrypt(data)    super.send(str, callback);  }  receive(data: any) {    this.postMessage(PostMessageType.ON_MESSAGE, _decode(data))  }  postMessage(type: PostMessageType, e?: any) {}}

    Worker

    创建一个 websocketWorker.js

    const URL = "ws://localhost:8181"import Socket from "./socket";const ws = new Socket(URL)self.addEventListener('message', (e) => {  const { type, data } = e.data  switch (type) {    case "init":      ws.init();      break    case "message":      ws.send(data)      break    case "close":      ws.close()      break    default:      console.error("发送websocket命令有误")      break  }})
    <script setup>import Worker from './websocketWorker?worker'const worker = new Worker()worker.onmessage = function (e) {  console.log(e.data)}function register() {  worker.postMessage({    type: 'init'  })}function close() {  worker.postMessage({    type: 'close'  })}</script><template>  <div>    <button @click="register">注册</button>    <button @click="close">关闭服务</button>  </div></template>

    vite 使用 worker 可以查看 worker选项

    如果是 webpack 可以查看 worker-loader

    module.exports = {  chainWebpack: config => {    config.module      .rule('worker')      .test(/.worker.js$/)      .use('worker-loader')      .loader('worker-loader')      .options({        inline: 'no-fallback',      })      .end()    config.module.rule('js').exclude.add(/.worker.js$/)  }}

    这里是我的配置

    读到这里,这篇“Web Worker线程electron问题怎么解决”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

    --结束END--

    本文标题: Web Worker线程electron问题怎么解决

    本文链接: https://www.lsjlt.com/news/345474.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • Web Worker线程electron问题怎么解决
      本文小编为大家详细介绍“Web Worker线程electron问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“Web Worker线程electron问题怎么解决”文章能帮助大家解决疑惑,下面跟着小编的思路...
      99+
      2023-07-04
    • qt线程抢占问题怎么解决
      Qt线程抢占问题指的是多个线程同时访问共享资源时可能导致的数据竞争和不确定性的问题。下面是一些解决Qt线程抢占问题的方法: 使用互...
      99+
      2024-02-29
      qt
    • Java多线程之线程安全问题怎么解决
      本篇内容主要讲解“Java多线程之线程安全问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java多线程之线程安全问题怎么解决”吧!1.线程安全概述1.1什么是线程安全问题首先我们需要...
      99+
      2023-06-30
    • Java多线程死锁问题怎么解决
      解决Java多线程死锁问题的常用方法有以下几种:1. 避免使用多个锁:尽量减少使用多个锁来降低出现死锁的概率。2. 按照固定的顺序获...
      99+
      2023-09-22
      Java
    • Python之ThreadPoolExecutor线程池问题怎么解决
      本文小编为大家详细介绍“Python之ThreadPoolExecutor线程池问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python之ThreadPoolExecutor线程池问题怎么解决”文章能帮助大家解决疑惑,下面跟...
      99+
      2023-07-05
    • MFC多线程传参问题怎么解决
      本篇内容主要讲解“MFC多线程传参问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MFC多线程传参问题怎么解决”吧!在一个程序中,这些独立运行的程序片断叫作“线程”(Thread),利...
      99+
      2023-06-17
    • java treemap线程安全问题怎么解决
      要解决Java TreeMap的线程安全问题,有以下几种方法:1. 使用Collections.synchronizedMap()方...
      99+
      2023-10-20
      java
    • golang map线程安全问题怎么解决
      在Go语言中,Map是并发不安全的,如果多个goroutine同时对同一个Map进行读写操作,可能会导致数据竞争问题。 为了解决Ma...
      99+
      2024-02-29
      golang
    • 怎么解决Web乱码的问题
      本篇文章为大家展示了怎么解决Web乱码的问题,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Web数据提交有两种方法:GET 和 POST。关于这两种方法的介绍,请看...
      99+
      2024-04-02
    • springboot多线程高并发问题怎么解决
      要解决Spring Boot多线程高并发问题,你可以考虑以下几个方面:1. 线程池配置:合理配置线程池的大小、队列容量等参数,以满足...
      99+
      2023-08-24
      springboot
    • Java SimpleDateFormat线程不安全问题怎么解决
      本篇内容主要讲解“Java SimpleDateFormat线程不安全问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java SimpleDateFormat线程...
      99+
      2023-07-05
    • python多线程效率低问题怎么解决
      Python中的多线程效率低的问题主要是由于Python的全局解释器锁(GIL)导致的。GIL是Python解释器中的一个机制,它确...
      99+
      2023-09-04
      python
    • Python线程怎么解决共享变量问题
      这篇文章主要介绍“Python线程怎么解决共享变量问题”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Python线程怎么解决共享变量问题”文章能帮助大家解决问题。下面展示另一种转账的方式:impor...
      99+
      2023-06-29
    • Python互斥锁怎么解决多线程问题
      这篇文章给大家分享的是有关Python互斥锁怎么解决多线程问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。python主要应用领域有哪些1、云计算,典型应用OpenStack。2、WEB前端开发,众多大型网站均...
      99+
      2023-06-14
    • web前端跨域问题怎么解决
      本文小编为大家详细介绍“web前端跨域问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“web前端跨域问题怎么解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。为什么跨域?为什么会出现跨域问题呢?那就不...
      99+
      2023-06-29
    • vue-electron使用serialport时问题解决方案
      报错如下: Uncaught TypeError: Cannot read property 'modules' of undefined at Object.eval (webp...
      99+
      2024-04-02
    • 解决Electron store的commit和dispatch不好用问题
      目录一、Electron使用store的commit和dispatch问题二、解决方法有两个方法1方法2总结Vue 的Vuex 一般vue的commit和dispatch可以直接使用...
      99+
      2023-01-10
      Electron store Electron stor commit Electron stor dispatch
    • vue3 keepalive线上问题怎么解决
      1、keepalive功能keepalive是vue3中的一个全局组件keepalive 本身不会渲染出来,也不会出现在dom节点当中,但是它会被渲染为vnode,通过vnode可以跟踪到keepalive中的cache和keys,当然也是...
      99+
      2023-05-19
      Vue3 keepalive
    • WebWorker线程解决方案electron踩坑记录
      目录初始化项目编写入口文件和 electron 插件websocketwebsocket 服务连接 websocket 服务发送心跳取消心跳重新连接其它优化Worker初始化项目 e...
      99+
      2022-11-13
      Web Worker线程electron Web Worker
    • java怎么使用多线程解决主线程提前结束问题
      这篇文章主要介绍“java怎么使用多线程解决主线程提前结束问题”,在日常操作中,相信很多人在java怎么使用多线程解决主线程提前结束问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java怎么使用多线程解决...
      99+
      2023-07-05
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作