html5支持多线程,html5 多线程

html5 多线程

版本:HTML5

运行者 Worker 接口是Web Workers API 的一部分,代表一个后台任务,它容易被创建并向创建者发回消息。创建一个运行者只要简单的调用Worker()构造函数,指定一个脚本,在工作线程中执行。

运行者能够依序产生新(嵌套)的运行者,只要这些运行者有同源(origin)的父页面(注意:Blink暂时不支持嵌套 Worker)。 此外,运行者还能够使用 XMLHttpRequest 实现网络 I/O 操作, 只不过 XMLHttpRequest上的 responseXML 与 channel 两个属性值始终返回 null。

运行者 Workder 支持的函数 页面提供了一个 worker 支持的全局函数列表。

火狐浏览器中, 如果在扩展使用运行者,不应使用(js-ctypes),应该使用 ChromeWorker 对象。

浏览器支持1878cdc442c78be424141e8d23fcc3f4.gif97025d18480c559ff507c6e3a9b8aac8.gif6f7088d28d6f7ea604e66cfba3b1e71d.gifbe610315b796c1b1d41a4e5496e268a7.gif2a97a8c5460fd66b35928591ac5b9c39.gif

Internet Explorer 10 以上版本支持

构造函数

Worker():创建一个专用Web worker,它只执行URL指定的脚本。Worker不指定URL时,而由使用Blob创建。

属性

继承父对象EventTarget 的属性,以及实现对象 AbstractWorker的属性。

事件句柄AbstractWorker.onerror:当ErrorEvent 类型的事件冒泡到 worker 时,事件监听函数 EventListener 被调用. 它继承于 AbstractWorker。

Worker.onmessage:当MessageEvent类型的事件冒泡到 worker 时,事件监听函数 EventListener 被调用. 例如,一个消息通过 DedicatedWorkerGlobalScope.postMessage,从执行者发送到父页面对象,消息保存在事件对象的 data 属性中。

Worker.onmessageerror:当messageerror 类型的事件发生时,对应的EventHandler 代码被调用。

方法

继承父对象EventTarget 的方法,以及实现对象 AbstractWorker的方法。Worker.postMessage():发送一条消息到最近的外层对象,消息可由任何 JavaScript 对象组成。

Worker.terminate():立即终止 worker。该方法不会给 worker 留下任何完成操作的机会;就是简单的立即停止。Service Woker 不支持这个方法。

示例

下面的代码通过构造函数Worker()创建了一个 Worker 对象。

var myWorker = new Worker('worker.js');

var first = document.querySelector('#number1');

var second = document.querySelector('#number2');

first.onchange = function()

{

myWorker.postMessage([first.value,second.value]);

console.log('Message posted to worker');

}

以前我们总说,JS是单线程没有多线程,当JS在页面中运行长耗时同步任务的时候就会导致页面假死影响用户体验,从而需要设置把任务放在任务队列中;执行任务队列中的任务也并非多线程进行的,然而现在HTML5提供了我们前端开发这样的能力 - Web Workers API,我们一起来看一看 Web Worker 是什么,怎么去使用它,在实际生产中如何去用它来进行产出。

1. 概述

Web Workers 使得一个Web应用程序可以在与主执行线程分离的后台线程中运行一个脚本操作。这样做的好处是可以在一个单独的线程中执行费时的处理任务,从而允许主(通常是UI)线程运行而不被阻塞。

它的作用就是给JS创造多线程运行环境,允许主线程创建worker线程,分配任务给后者,主线程运行的同时worker线程也在运行,相互不干扰,在worker线程运行结束后把结果返回给主线程。这样做的好处是主线程可以把计算密集型或高延迟的任务交给worker线程执行,这样主线程就会变得轻松,不会被阻塞或拖慢。这并不意味着JS语言本身支持了多线程能力,而是浏览器作为宿主环境提供了JS一个多线程运行的环境。

不过因为worker一旦新建,就会一直运行,不会被主线程的活动打断,这样有利于随时响应主线程的通性,但是也会造成资源的浪费,所以不应过度使用,用完注意关闭。或者说:如果worker无实例引用,该worker空闲后立即会被关闭;如果worker实列引用不为0,该worker空闲也不会被关闭。

看一看它的兼容性

e3a02d029aae3eabc3ca53869fd27d71.png

2. 使用

2.1 限制

worker线程的使用有一些注意点同源限制:worker线程执行的脚本文件必须和主线程的脚本文件同源,这是当然的了,总不能允许worker线程到别人电脑上到处读文件吧

文件限制:为了安全,worker线程无法读取本地文件,它所加载的脚本必须来自网络,且需要与主线程的脚本同源

DOM操作限制:worker线程在与主线程的window不同的另一个全局上下文中运行,其中无法读取主线程所在网页的DOM对象,也不能获取document、window等对象,但是可以获取navigator、location(只读)、XMLHttpRequest、setTimeout族等浏览器API。

通信限制:worker线程与主线程不在同一个上下文,不能直接通信,需要通过postMessage方法来通信。

脚本限制:worker线程不能执行alert、confirm,但可以使用XMLHttpRequest对象发出ajax请求。

2.2 例子

在主线程中生成 Worker 线程很容易:

var myWorker = new Worker(jsUrl, options);

Worker()构造函数,第一个参数是脚本的网址(必须遵守同源政策),该参数是必需的,且只能加载 JS 脚本,否则报错。第二个参数是配置对象,该对象可选。它的一个作用就是指定 Worker 的名称,用来区分多个 Worker 线程。

// 主线程

var myWorker = new Worker('worker.js', { name : 'myWorker' });

// Worker 线程

self.name

关于api什么的,直接上例子大概就能明白了,首先是worker线程的js文件:

// workerThread1.js

let i = 1

function simpleCount()

{

i++

self.postMessage(i)

setTimeout(simpleCount, 1000)

}

simpleCount()

self.onmessage = ev =>

{

postMessage(ev.data + ' 呵呵~')

}

在HTML文件中的body中:

Worker 输出内容:

发送

stop!

if (typeof(Worker) === 'undefined') // 使用Worker前检查一下浏览器是否支持

document.writeln(' Sorry! No Web Worker support.. ')

else {

window.w = new Worker('workerThread1.js')

window.w.onmessage = ev => {

document.getElementById('app').innerHTML = ev.data

}

window.w.onerror = err => {

w.terminate()

console.log(error.filename, error.lineno, error.message) // 发生错误的文件名、行号、错误内容

}

function sendMessage() {

const msg = document.getElementById('msg')

window.w.postMessage(msg.value)

}

function stopWorker() {

window.w.terminate()

}

}

可以自己运行一下看看效果,上面用到了一些常用的api

主线程中的api,worker表示是 Worker 的实例:worker.postMessage: 主线程往worker线程发消息,消息可以是任意类型数据,包括二进制数据

worker.terminate: 主线程关闭worker线程

worker.onmessage: 指定worker线程发消息时的回调,也可以通过worker.addEventListener('message',cb)的方式

worker.onerror: 指定worker线程发生错误时的回调,也可以worker.addEventListener('error',cb)

Worker线程中全局对象为self,代表子线程自身,这时this指向self,其上有一些api:self.postMessage: worker线程往主线程发消息,消息可以是任意类型数据,包括二进制数据

self.close: worker线程关闭自己

self.onmessage: 指定主线程发worker线程消息时的回调,也可以self.addEventListener('message',cb)

self.onerror: 指定worker线程发生错误时的回调,也可以self.addEventListener('error',cb)

注意,w.postMessage(aMessage, transferList)方法接受两个参数,aMessage是可以传递任何类型数据的,包括对象,这种通信是拷贝关系,即是传值而不是传址,Worker 对通信内容的修改,不会影响到主线程。事实上,浏览器内部的运行机制是,先将通信内容串行化,然后把串行化后的字符串发给 Worker,后者再将它还原。一个可选的 Transferable对象的数组,用于传递所有权。如果一个对象的所有权被转移,在发送它的上下文中将变为不可用(中止),并且只有在它被发送到的worker中可用。可转移对象是如ArrayBuffer,MessagePort或ImageBitmap的实例对象,transferList数组中不可传入null。

更详细的API参见 MDN - WorkerGlobalScope。

worker线程中加载脚本的api:

importScripts('script1.js') // 加载单个脚本

importScripts('script1.js', 'script2.js') // 加载多个脚本

3. 实战场景

个人觉得,Web Worker我们可以当做计算器来用,需要用的时候掏出来摁一摁,不用的时候一定要收起来~加密数据:有些加解密的算法比较复杂,或者在加解密很多数据的时候,这会非常耗费计算资源,导致UI线程无响应,因此这是使用Web Worker的好时机,使用Worker线程可以让用户更加无缝的操作UI。

预取数据:有时候为了提升数据加载速度,可以提前使用Worker线程获取数据,因为Worker线程是可以是用XMLHttpRequest的。

预渲染:在某些渲染场景下,比如渲染复杂的canvas的时候需要计算的效果比如反射、折射、光影、材料等,这些计算的逻辑可以使用Worker线程来执行,也可以使用多个Worker线程,这里有个射线追踪的示例。

复杂数据处理场景:某些检索、排序、过滤、分析会非常耗费时间,这时可以使用Web Worker来进行,不占用主线程。

预加载图片:有时候一个页面有很多图片,或者有几个很大的图片的时候,如果业务限制不考虑懒加载,也可以使用Web Worker来加载图片,可以参考一下这篇文章的探索,这里简单提要一下。

// 主线程

let w = new Worker("js/workers.js");

w.onmessage = function (event) {

var img = document.createElement("img");

img.src = window.URL.createObjectURL(event.data);

document.querySelector('#result').appendChild(img)

}

// worker线程

let arr = [...好多图片路径];

for (let i = 0, len = arr.length; i < len; i++) {

let req = new XMLHttpRequest();

req.open('GET', arr[i], true);

req.responseType = "blob";

req.setRequestHeader("client_type", "DESKTOP_WEB");

req.onreadystatechange = () => {

if (req.readyState == 4) {

postMessage(req.response);

}

}

req.send(null);

}

在实战的时候注意虽然使用worker线程不会占用主线程,但是启动worker会比较耗费资源

主线程中使用XMLHttpRequest在请求过程中浏览器另开了一个异步http请求线程,但是交互过程中还是要消耗主线程资源

在 Webpack 项目里面使用 Web Worker 请参照:怎么在 ES6+Webpack 下使用 Web Worker

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

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

相关文章

magento tab(easy tables)标签应用

我介绍的主要是magento 1.7.0.2版本。 因为彼人刚接触magento一星期&#xff0c;了解有限&#xff0c;理解有误的地方 还请多多包含。 easy tables 在1.7.0.2版本中&#xff0c;默认是在app/design/frontend/default/modern/layout/template/catalog.xml; 让我们先找到这个文件…

LeetCode 269. 火星词典(拓扑排序)

文章目录1. 题目2. 解题1. 题目 现有一种使用字母的全新语言&#xff0c;这门语言的字母顺序与英语顺序不同。 假设&#xff0c;您并不知道其中字母之间的先后顺序。 但是&#xff0c;会收到词典中获得一个 不为空的 单词列表。 因为是从词典中获得的&#xff0c;所以该单词列…

南工大计算机学院,江南-欢迎访问湖北工业大学计算机学院官方网站

科研情况介绍(研究方向、研究课题、现正进行的科研项目)研究方向&#xff1a;计算机软件与理论。近3年来主要个人成果、参加学术团体及社会兼职情况&#xff1a;1、机械化定理证明研究综述.第一作者.软件学报. 20192、mJava到Micro-Dalvik虚拟机的编译验证.第一作者.电子学报20…

邻接表的两种实现(链表和数组模拟)

struct node {int v; //边的结束顶点 int w; //边的长度node* next; //指向以同一起点的下一条边的指针 }*first[N]; //first[u]指向以u为起始点的第一条边 void init() {memset(first,NULL,sizeof(first)); } void add(int u, int v, int w)//添加边 {node* p new node;p->…

LeetCode 301. 删除无效的括号(回溯)

文章目录1. 题目2. 解题1. 题目 删除最小数量的无效括号&#xff0c;使得输入的字符串有效&#xff0c;返回所有可能的结果。 说明: 输入可能包含了除 ( 和 ) 以外的字符。 示例 1: 输入: "()())()" 输出: ["()()()", "(())()"]示例 2: 输入:…

计算机程序专利实用新型,涉及计算机程序的实用新型专利保护的思考

随着信息技术的不断发展&#xff0c;与计算机程序相关的计算机技术以及通信技术渗透到各个领域&#xff0c;越来越多的专利涉及了与计算机程序相关的技术。那么&#xff0c;是否包含计算机程序的相关专利申请都不能被授予实用新型专利权呢&#xff1f;本文从一件复审案例出发&a…

javascript数组去重方法性能测试比较

昨天参加的一个前端面试&#xff0c;其中有一题数组去重&#xff0c;首先想到的是对象存键值的方法&#xff0c;代码如下 方法一&#xff1a;&#xff08;简单存键值&#xff09; Array.prototype.distinct1 function() {var i0,tmp{},thatthis.slice(0)this.length0;for(;i&l…

LeetCode 428. 序列化和反序列化 N 叉树(DFS)

文章目录1. 题目2. 解题1. 题目 序列化是指将一个数据结构转化为位序列的过程&#xff0c;因此可以将其存储在文件中或内存缓冲区中&#xff0c;以便稍后在相同或不同的计算机环境中恢复结构。 设计一个序列化和反序列化 N 叉树的算法。 一个 N 叉树是指每个节点都有不超过 N…

计算机进入休眠状态后,Win7电脑进入休眠状态后又自动重启该怎么处理

在使用win7系统的时候&#xff0c;有的小伙伴遇到了一个莫名其妙的问题&#xff1a;当电脑进入休眠状态后却突然自动重启了&#xff0c;那么这是怎么一回事呢&#xff1f;又该如何解决呢&#xff1f;别着急&#xff0c;接下来&#xff0c;小编就给大家分享一下Win7电脑进入休眠…

Syslistview32+Systreeview32系统操作动态链接库和实际的商业化

Syslistview32和Systreeview32 是两个极其常用的系统控件&#xff0c;一个是列表控件&#xff0c;一个是树形框&#xff0c;只要能随意操控这两个控件就能够从外部控制住大多应用到这两个控件的软件。 一开始是想要控制VS平台的列表框来操作自动进房间&#xff0c;但是苦于没有…

LeetCode 325. 和等于 k 的最长子数组长度(哈希表记录第一次出现的状态)

文章目录1. 题目2. 解题1. 题目 给定一个数组 nums 和一个目标值 k&#xff0c;找到和等于 k 的最长子数组长度。 如果不存在任意一个符合要求的子数组&#xff0c;则返回 0。 注意: nums 数组的总和是一定在 32 位有符号整数范围之内的。 示例 1: 输入: nums [1, -1, 5, -…

测试网上哪款软件最好,手机测试软件哪款好用?4款测试软件推荐

手机强不强测试上见真章&#xff01;不服测个试呗&#xff01;虽不能代表作手机的品质&#xff0c;但可以直观的反馈出手机硬件性能。通过专业的手机测试软件可以对手机硬件进行评分&#xff0c;了解手机每个硬件性能情况。鲁大师&#xff1a;《鲁大师》是一款支持Android、平板…

Android4开发入门经典 之 第七部分:数据存储

数据存储基本知识 Android系统提供了多种数据存储的方式&#xff0c;如下&#xff1a; 1&#xff1a;Shared Preferences&#xff1a;用来存储私有的、原始类型的、简单的数据&#xff0c;通常是Key-value对2&#xff1a;Internal Storage&#xff1a;在设备内部存储器中存储数…

LeetCode 218. 天际线问题(multiset优先队列)*

文章目录1. 题目2. 解题1. 题目 城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。 现在&#xff0c;假设您获得了城市风光照片&#xff08;图A&#xff09;上显示的所有建筑物的位置和高度&#xff0c;请编写一个程序以输出由这些建筑物形成的天际线&#x…

计算机显示器性能指标的是,简述显示器的主要性能指标

1&#xff0e;分辨率&#xff1a;LCD的分辨率与CRT显示器不同&#xff0c;一般不能任意调整&#xff0c;它是制造商所设置和规定的。分辨率是指屏幕上每行有多少像素点、每列有多少像素点&#xff0c;一般用矩阵行列式来表示&#xff0c;其中每个像素点都能被计算机单独访问。现…

LeetCode 277. 搜寻名人(思维题)

文章目录1. 题目2. 解题2.1 暴力解2.2 高效解1. 题目 假设你是一个专业的狗仔&#xff0c;参加了一个 n 人派对&#xff0c;其中每个人被从 0 到 n - 1 标号。 在这个派对人群当中可能存在一位 “名人”。 所谓 “名人” 的定义是&#xff1a;其他所有 n - 1 个人都认识他/她&…

最近很火的计算机歌曲,抖音日活跃用户数超4亿 2019年度最火音乐竟是它

抖音今日发布《2019抖音数据报告》(以下简称报告)&#xff0c;报告显示&#xff0c;截至2020年1月5日&#xff0c;抖音日活跃用户数超过4亿。根据报告&#xff0c;抖音上不同年龄段用户最爱拍摄的内容不尽相同&#xff0c;00后喜欢拍摄二次元相关视频&#xff0c;90后用户喜欢拍…

LeetCode 432. 全 O(1) 的数据结构(设计题)*

文章目录1. 题目2. 解题1. 题目 请你实现一个数据结构支持以下操作&#xff1a; Inc(key) - 插入一个新的值为 1 的 key。 或者使一个存在的 key 增加一&#xff0c;保证 key 不为空字符串。Dec(key) - 如果这个 key 的值是 1&#xff0c;那么把他从数据结构中移除掉。 否则使…

vs2010 rdlc 报表及报表控件

有个winfrom项目要使用报表&#xff0c;数据来源于自定义类&#xff08;model&#xff09;&#xff0c;从网上找了好多教程&#xff0c;都是说如何拖控件&#xff0c;如何设值之类的。没有我想要的效果。 我想要的效果&#xff1a;将rdlc文件放到Debug目录下&#xff0c;以便一…

服务器如何安装应用程序,第四节 服务器端应用程序安装

1、友情提示&#xff1a;退路①备份配置文件Linux 系统环境下配置文件通常内容很多。如果不小心修改了不该修改的地方&#xff0c;自己有不记得做了修改&#xff0c;那么将来报错很难找到错误位置。为了避免这样的问题&#xff0c;我们可以在修改任何配置文件之前都多复制一份&…