HTML5中的Web Workers

http://www.javashuo.com/article/p-mqjznazm-g.htmljavascript

http://www.javashuo.com/article/p-xvypszop-h.htmlhtml

HTML5 工做线程原理

传统上的线程能够解释为轻量级进程,它和进程同样拥有独立的执行控制,通常状况下由操做系统负责调度。而在 HTML5 中的多线程是这样一种机制,它容许在 Web 程序中并发执行多个 JavaScript 脚本,每一个脚本执行流都称为一个线程,彼此间互相独立,而且由浏览器中的 JavaScript 引擎负责管理。下面咱们将详细讲解 HTML5 的工做线程原理。java

Web Workers 是浏览器内置的线程因此能够被用来执行非阻塞事件循环的 JavaScript 代码。node

在 HTML5 中引入的工做线程使得浏览器端的 JavaScript 引擎能够并发地执行 JavaScript 代码,从而实现了对浏览器端多线程编程的良好支持。将可能耗费较长时间的处理交给后台执行,则对用户在前台页面中执行的操做没有影响。git

HTML5 中的 Web Worker 能够分为两种不一样线程类型,一个是专用线程 Dedicated Worker,一个是共享线程 Shared Worker。两种类型的线程各有不一样的用途。github

应用场景一:使用工做线程作后台数值复杂(算法)计算web

应用场景二:使用共享线程处理多用户并发链接算法

应用场景三:高频的用户交互编程

应用场景四:监听由后台服务器广播的消息canvas

 

例子:

//worker.js
onmessage =function (evt){
var d = evt.data;//经过evt.data得到发送来的数据
postMessage( d );//将获取到的数据发送会主线程
}

HTML页面:test.html

复制代码
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="text/javascript">
//WEB页主线程
var worker =new Worker("worker.js"); //建立一个Worker对象并向它传递将在新线程中执行的脚本的URL
worker.postMessage("hello world"); //向worker发送数据
worker.onmessage =function(evt){ //接收worker传过来的数据函数
console.log(evt.data); //输出worker发送来的数据
}
</script>
</head>
<body></body>
</html>
复制代码

使用web worker主要分为如下几部分:

WEB主线程:

1.经过 worker = new Worker( url ) 加载一个JS文件来建立一个worker,同时返回一个worker实例。

2.经过worker.postMessage( data ) 方法来向worker发送数据。

3.绑定worker.onmessage方法来接收worker发送过来的数据。

4.可使用 worker.terminate() 来终止一个worker的执行。

worker新线程:

1.经过postMessage( data ) 方法来向主线程发送数据。

2.绑定onmessage方法来接收主线程发送过来的数据。

 

Web Workers可以为用户作些什么?

加载一个JavaScript文件,进行大量的复杂计算,而不挂起主进程,并经过postMessage和onMessage进行通讯。

能够在WoOer(worker)中经过importScripts(url)方法加载另外的JavaScript脚本文件。

可使用setTimeout()、clearTimeout()、setInterval()和clearInterval()。

可使用XMLHttpRequest进行异步请求。

能够访问navigator的部分属性。

可使用JavaScript核心对象。

监听由后台服务器广播的消息。

web Workers的局限性:

1.不能跨域加载JS

2.worker内代码不能访问DOM()、window 对象、document 对象、parent 对象

3.各个浏览器对Worker的实现不大一致,例如FF里容许worker中建立新的worker,而Chrome中就不行

4.不是每一个浏览器都支持这个新特性

 

 

 

ECMscript规定的一些基本语法以及规定的一些操做。以下操做:

•navgator :  ppVersion、userAgent、platform
•location  :   全部属appName、a性都是只读的
•self  :  指向全局 worker 对象
•全部的ECMA对象,Object、Array、Date等
•XMLHttpRequest构造器
•setTimeout和setInterval方法
•close()方法,马上中止worker运行
•importScripts方法

 

Web Workers 最佳使用场景

迄今为止,咱们列举了 Web Workers 的长处及其限制。让咱们看看他们的最佳使用场景:

  • 射线追踪:射线追踪是一项经过追踪光线的路径做为像素来生成图片的渲染技术。Ray tracing 使用 CPU 密集型计算来模仿光线的路径。思路即模仿一些诸如反射,折射,材料等的效果。全部的这些计算逻辑能够放在 Web Worker 中以免阻塞 UI 线程。甚至更好的方法即-你能够轻易地把把图片的渲染拆分在几个 workers 中进行(即在各自的 CPU 中进行计算,意思是说利用多个 CPU 来进行计算,能够参考下 nodejs 的 api)。这里有一个使用 Web Workers 来进行射线追踪的简单示例-https://nerget.com/rayjs-mt/r...
  • 加密:端到端的加密因为对保护我的和敏感数据日益严格的法律规定而变得愈来愈流行。加密有时候会很是地耗时,特别是若是当你须要常常加密不少数据的时候(好比,发往服务器前加密数据)。这是一个使用 Web Worker 的绝佳场景,由于它并不须要访问 DOM 或者利用其它魔法-它只是纯粹使用算法进行计算而已。一旦在 worker 进行计算,它对于用户来讲是无缝地且不会影响到用户体验。
  • 预取数据:为了优化网站或者网络应用及提高数据加载时间,你可使用 Workers 来提早加载部分数据以备不时之需。不像其它技术,Web Workers 在这种状况下是最棒哒,由于它不会影响程序的使用体验。
  • 渐进式网络应用:即便在网络不稳定的状况下,它们必须快速加载。这意味着数据必须本地存储于浏览器中。这时候 IndexDB 及其它相似的 API 就派上用场了。大致上说,一个客户端存储是必须的。为了避免阻塞 UI 线程的渲染,这项工做必须由 Web Workers 来执行。呃,当使用 IndexDB的时候,能够不使用 workers 而使用其异步接口,可是以前它也含有同步接口(可能会再次引入 ),这时候就必须在 workers 中使用 IndexDB。

    这里须要注意的是在现代浏览器已经不支持同步接口了,具体可查看这里

  • 拼写检查:一个基本的拼写检测器是这样工做的-程序会读取一个包含拼写正确的单词列表的字典文件。字典会被解析成一个搜索树以加快实际的文本搜索。当检查器检查一个单词的时候,程序会在预构建搜索树中进行检索。若是在树中没有检索到,则会经过提供替代的字符为用户提供替代的拼写并检测单词是不是有效-是不是用户须要的单词。这个检索过程当中的全部工做均可以交由 Web Worker 来完成,这样用户就只需输入单词和语句而不会阻塞 UI,与此同时 worker 会处理全部的搜索和服务建议。

 

例子:

实际工做过程会遇到用户须要经过解析远程图片来得到图片 base64 的案例,那么这时候,若是图片很是大,就会形成 canvas 的 toDataURL 操做至关的耗时,从而阻塞页面的渲染。

因此解决思路即把这里的处理图片的操做交由 worker 来处理。如下贴出主要的代码:

<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>Canvas to base64</title> </head> <body> <script> function loadImageAsync(url) { if (typeof url !== 'string') { return Promise.reject(new TypeError('must specify a string')); } return new Promise(function(resolve, reject) { const image = new Image(); // 容许 canvas 跨域加载图片 image.crossOrigin="anonymous"; image.onload = function() { const $canvas = document.createElement('canvas'); const ctx = $canvas.getContext('2d'); const width = this.width; const height = this.height; let imageData; $canvas.width = width; $canvas.height = height; ctx.drawImage(image, 0, 0, width, height); imageData = ctx.getImageData(0, 0, $canvas.width, $canvas.height); resolve({image, imageData}); }; image.onerror = function() { reject(new Error('Could not load image at ' + url)); }; image.src = url; }); } function blobToDataURL(blob) { return new Promise((fulfill, reject) => { let reader = new FileReader(); reader.onerror = reject; reader.onload = (e) => fulfill(reader.result); reader.readAsDataURL(blob); }) } document.addEventListener("DOMContentLoaded", function () { loadImageAsync('https://cdn-images-1.medium.com/max/1600/1*4lHHyfEhVB0LnQ3HlhSs8g.png') .then(function (image) { // jpeg-web-worker.js https://github.com/kentmw/jpeg-web-worker const worker = new Worker('jpeg-web-worker.js'); worker.postMessage({ image: image.imageData, quality: 50 }); worker.onmessage = function(e) { // e.data is the imageData of the jpeg. {data: U8IntArray, height: int, width: int} // you can still convert the jpeg imageData into a blog like this: const blob = new Blob( [e.data.data], {type: 'image/png'} ); blobToDataURL(blob).then((imageURL) => { console.log('imageUrl:', imageURL); }) } }) .catch(function (err) { console.log('Error:', err.message); }); }); </script> </body> </html>

以上是经过 canvas 来获取图片数据,那么是否有其它方法呢?确定有的啦,动下脑筋吧少年。

相关文章
相关标签/搜索