IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Web Workers RPC -> 正文阅读

[网络协议]Web Workers RPC

CSDN话题挑战赛第2期
参赛话题:前端技术分享

说在前面

对于需要花费大量时间才能处理的任务,javascript 引擎通常会有两种现象:

  1. 执行当前任务花费大量的时间,使得无法执行任何其他操作,导致浏览卡顿
  2. 如果此时回调队列被阻塞的任务过多时,大多数浏览器都会抛出一个提示信息,征求是否要关闭网页
    在这里插入图片描述
    那么,我们如何在不阻塞UI并使浏览器正常响应的情况下执行繁重的代码呢?

引言

javascript 是单线程编程语言,这使得我们开发过程中不必关注因多线程导致的复杂场景(如,死锁)。

单线程意味着某一时刻只能做一件事情! javascript 引擎,以最常见的 v8 举例,内置了 事件循环 Event Loop + 回调队列 Callback Queue 机制,以及通过宏任务 macrotask + 微任务 microtask 来分配执行优先级,来确保高效运行。

因此,解决上述问题,通常有两种方案:

  1. 异步回调(asynchronous callbacks):依赖第三方服务
  2. 开启多线程(web worker):本文重点,浏览器提供了相应 web api

关于「JavaScript的工作原理」「Event loop及macrotask & microtask」相关内容,可阅读下述文章:

Web Workers

worker 的一个优势在于能够执行处理器密集型的运算而不会阻塞 UI 线程。

web workers 浏览器整体兼容性很好,为我们大面积使用奠定了基础~~~
在这里插入图片描述
在一个 worker 中最主要的是不能直接影响父页面,包括操作父页面的节点以及使用页面中的对象。只能间接地实现,通过 DedicatedWorkerGlobalScope.postMessage 回传消息给主脚本,然后从主脚本那里执行操作或变化。

worker 的优势明显,但在通信上的处理极其繁琐,导致大家使用的频次并不高。

Comlink 解决了通信的问题,其借助 Proxy 可以忽略所有繁琐的通信细节(无需考虑事件订阅所带来的复杂性),极大降低了 Worker 的维护成本。-- RPC方式

RPC 全称是 Remote Procedure Call,即远程过程调用。目的是:让我们调用远程方法像调用本地方法一样,无需了解底层网络技术的协议等。

案例

地址:https://github.com/381510688/practice/tree/master/web-api-test

传统写法

// index.js
const worker = new Worker('worker.js')
comput.addEventListener('click', function () {
  worker.postMessage({
    num1: num1.value,
    num2: num2.value
  })
})
worker.onmessage = function (msgEvent) {
  res.innerHTML = msgEvent.data
}

// worker.js
onmessage = function (msgEvent) {
  let {num1, num2} = msgEvent.data
  postMessage(Number(num1) + Number(num2))
}

尝试保留 add 方法

// index.js
const worker = new Worker('worker.js')
comput.addEventListener('click', function () {
  worker.postMessage('ok')
})
worker.onmessage = function (msgEvent) {
  res.innerHTML = msgEvent.data.add(num1.value, num2.value)
}

// worker.js
function add (num1, num2) {
  return Number(num1) + Number(num2)
}
onmessage = function (msgEvent) {
  postMessage({add: add})
}

UncaughtDOMException: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': function add (num1, num2) {}

Worker.postMessage()

Worker 接口的 postMessage()方法向worker的内部作用域发送一个消息。接受单个参数(要发送给worker的数据)。数据可以是由结构化克隆算法处理的任何值或JavaScript对象,其包括循环引用。

结构化克隆所不能做到的:

  • Error 以及 Function 对象是不能被结构化克隆算法复制的;如果你尝试这样子去做,这会导致抛出 DATA_CLONE_ERR 的异常。
  • 企图去克隆 DOM 节点同样会抛出 DATA_CLONE_ERR 异常。
  • 对象的某些特定参数也不会被保留
    • RegExp 对象的 lastIndex 字段不会被保留
    • 属性描述符,setters 以及 getters(以及其他类似元数据的功能)同样不会被复制。例如,如果一个对象用属性描述符标记为 read-only,它将会被复制为 read-write,因为这是默认的情况下。
    • 原形链上的属性也不会被追踪以及复制。

comlink 示例

// index.js
const worker = new Worker("worker.js");
const cw = Comlink.wrap(worker);
comput.addEventListener('click', async function () {
  let result = await cw(num1.value, num2.value)
  res.innerHTML = result
})

// worker.js
importScripts("https://unpkg.com/comlink/dist/umd/comlink.js");
function add (num1, num2) {
  return Number(num1) + Number(num2)
}
Comlink.expose(add);

本质上依然是 MessagePort 消息通讯,不过封装了我们所头疼的“操作判断”,并以一种更优雅的方式(Proxy + Promise)来处理。
在这里插入图片描述
在这里插入图片描述
Comlink 采用的 RPC 代理方式,并不是传递上下文环境(因为这是非常危险的,而且函数传递时会导致 Uncaught (in promise) DOMException: Failed to execute 'postMessage' on 'Worker': xxx could not be cloned. 报错)。

RPC:Remote Procedure Call,远程过程调用,指调用不同于当前上下文环境的方法,通常可以是不同的线程、域、网络主机,通过提供的接口进行调用。

index.html

import * as Comlink from "https://unpkg.com/comlink/dist/esm/comlink.mjs"

const worker = new Worker("worker.js")
const cw = Comlink.wrap(worker)
const cpt = await new cw()
comput.addEventListener('click', async function () {
  let result = await cpt.add(num1.value, num2.value)
  dom.innerHTML = result
})

worker.js

importScripts("https://unpkg.com/comlink/dist/umd/comlink.js")
class Comput {
  constructor () {}
  add (num1, num2) {
    return Number(num1) + Number(num2);
  }
  sub (num1, num2) {
    return Number(num1) - Number(num2);
  }
}
Comlink.expose(Comput)

importScripts() 将一个或多个脚本同步导入到工作者的作用域中。隶属于:WorkerGlobalScope 接口。

注意:new Worker('worker.js') scriptURL will be fetched and executed in the background, creating a new global environment for which worker represents the communication channel. – https://html.spec.whatwg.org/multipage/workers.html#dom-worker-dev

总结

Comlink(RPC方式)使我们可以更多的关注业务内容,忽略调用(网络)细则。
在这里插入图片描述
客户端应用程序调用本地存根(stub),而不是调用实际代码;服务端应用程序接受参数,通过服务器存根(stub)检索实际代码进行运行。

链接

  • JS性能基准:https://github.com/zxch3n/js-performance
  • 本机测试:https://zxch3n.github.io/js-performance/
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 21:27:49  更:2022-09-24 21:28:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 5:41:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计