可以将CanvasPixelArray获取的via 发送getImageData到worker脚本,让worker脚本操纵其后台线程中的像素,最后将操作的像素阵列发回.
但是,我使用的是原生画布绘图功能drawImage.这些drawImage调用当前正在阻止UI线程.这会导致按钮重绘速度慢,单击按钮时会出现明显的延迟,这只是为了说明一些缺点.(编辑:现在可以使用ctx.imageSmoothingEnabled = false至少在带有webkit前缀的WebKit上完成一项小改进.)
我想使用Web Workers将绘图从主线程移动到后台线程中.但是,我似乎无法向工作人员发送画布和上下文.
注意:像往常一样,后台线程(包括worker)无法操纵DOM.如果后台线程采取的操作需要导致对DOM的更改,则应将消息发送回其创建者以执行该工作.
但是我想按原样离开DOM; 我只是想在canvas元素上绘制东西.这是可能的,还是Web Workers真的只允许计算而不是绘制?
(或者也许可以使用类似drawImage操作CanvasPixelArray而不是在画布上绘制的函数?)
我们可以像HTML5一样使用HTML5中的web worker:
var worker = new Worker('worker.js');
Run Code Online (Sandbox Code Playgroud)
但为什么我们不能称这样的函数?
var worker = new Worker(function(){
//do something
});
Run Code Online (Sandbox Code Playgroud) 我曾尝试使用importScripts将第二个JavaScript文件加载到我的Web worker中,但是虽然没有发生错误但它没有用.我把问题缩小到这个非常简单的情况:
在主HTML文件中:
<script>
var w = new Worker("script1.js");
w.addEventListener("message", function(e){
alert(e.data);
})
w.postMessage();
</script>
Run Code Online (Sandbox Code Playgroud)
在script1.js中:
self.addEventListener("message", function(e){
var a = 5;
importScripts("script2.js");
self.postMessage(a);
})
Run Code Online (Sandbox Code Playgroud)
在script2.js中:
a = 6
Run Code Online (Sandbox Code Playgroud)
我想看到一个显示6的对话框,因为a通过导入script2.js从5更改为6,但对话框显示5.我在这里缺少什么?
阅读Angular文档,您可以找到几个引用Web Worker中的整个Angular应用程序的引用,因此您的UI不会被大量的JS使用阻止.
但是,目前还没有关于如何做到这一点的官方信息,以及Angular Doc中的唯一信息.这是一个实验性的功能.
我如何使用这种方法来利用Angular中的Web工作者?
我目前有这个代码来创建一个Web Worker:
w = new Worker("webwork.js");
w.onmessage = function(event) { alert(event.data); }
Run Code Online (Sandbox Code Playgroud)
然后是webwork.jsWeb Worker 的代码:
self.onmessage = function(event) {
//var ss=r; //Causes error because of undefined
var ss="";
for(var currProp in event) {
ss+=("event."+currProp+"="+event[currProp]+"\n");
}
postMessage(ss);
}
Run Code Online (Sandbox Code Playgroud)
现在我想ArrayBuffer用这段代码传输128兆字节:
var r = new ArrayBuffer(1048576*128);
w.postMessage(0, [r]);
Run Code Online (Sandbox Code Playgroud)
既然我已经转移了变量r,我该如何从Web Worker本身访问它.我已经试过event.r,只是r,self.r和喜欢尝试添加第二个函数参数为数组其他东西ArrayBuffers,但没有任何工程.
如何从Web Worker访问传输的变量?
我正在尝试在Web worker中执行时提高脚本的性能.它旨在解析浏览器中的大型文本文件而不会崩溃.一切都运行良好,但我注意到使用Web worker时大文件的性能存在严重差异.
所以我进行了一个简单的实验.我在同一个输入上运行了两次脚本.第一次运行在页面的主线程中执行脚本(没有web worker).当然,这会导致页面冻结并变得无法响应.对于第二次运行,我在Web worker中执行了脚本.
对于本实验中的小文件(<~100 MB),性能差异可以忽略不计.但是,对于大型文件,解析在工作线程中需要大约20倍:

预计蓝线.它只需要大约11秒来解析文件,性能相当稳定:

红线是Web worker中的性能.更令人惊讶的是:

前30秒的锯齿状线是正常的(jag是由解析文件的每个块后将结果发送到主线程的轻微延迟引起的).但是,解析在30秒时相当突然减慢.(请注意,我只使用一个Web工作者来完成工作;一次只能使用一个工作线程.)
我已经确认延迟不是将结果发送到主线程的postMessage().减速是在解析器的紧密循环中,这完全是同步的.由于我无法解释的原因,该循环显着减慢并且在30秒后随着时间变慢.
但这只发生在网络工作者身上.正如您在上面看到的那样,在主线程中运行相同的代码,运行非常顺畅和快速.
为什么会这样?我该怎么做才能提高性能?(我不希望任何人完全理解该文件中的所有1,200多行代码.如果你这样做,那真是太棒了,但我觉得这与网络工作者的关系比我的代码更多,因为它在主文件中运行良好线.)
系统:我在Mac OS 10.9.4上运行Chrome 35,内存为16 GB; 四核2.7 GHz Intel Core i7,具有256 KB L2缓存(每个核心)和3 MB的L3缓存.文件块大小约为10 MB.
更新:刚刚在Firefox 30上尝试过它并没有在工作线程中遇到同样的减速(但是在主线程中运行时它比Chrome慢).然而,尝试使用更大的文件(大约1 GB)进行相同的实验,在大约35-40秒(看起来)之后产生了显着的减速.
javascript performance multithreading google-chrome web-worker
当我尝试使用Web worker时,我遇到了一些正确编译我的打字稿的问题.
我有一个像这样定义的工人:
onmessage = (event:MessageEvent) => {
var files:FileList = event.data;
for (var i = 0; i < files.length; i++) {
postMessage(files[i]);
}
};
Run Code Online (Sandbox Code Playgroud)
在我的应用程序的另一部分,我正在使用webpack worker loader来加载我的worker,如下所示: let Worker = require('worker!../../../workers/uploader/main');
然而,当我需要编译应用程序时,我会遇到一些问题,使得打字稿声明不会对我大喊大叫.根据我的研究,我必须在我的tsconfig文件中添加另一个标准库,以公开worker需要访问的全局变量.这些我指定如下:
{
"compilerOptions": {
"lib": [
"webworker",
"es6",
"dom"
]
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当我运行webpack让它构建一切时,我得到了一堆这样的错误: C:/Users/hanse/Documents/Frontend/node_modules/typescript/lib/lib.webworker.d.ts:1195:13
Subsequent variable declarations must have the same type. Variable 'navigator' must be of type 'Navigator', but here has type 'WorkerNavigator'.
所以我的问题是:如何指定webworker使用lib.webworker.d.ts定义,其他一切遵循正常的定义?
我正在使用ES2015导入/导出模块.
在我的工作文件中,当我尝试导入像我通常那样的函数时:
worker.js
import { a, b, c } from "./abc.js";
Run Code Online (Sandbox Code Playgroud)
我收到错误:
SyntaxError: import declarations may only appear at top level of a module
当我在我的模块'abc.js'中导出函数时,我不知道如何使用旧的(显然在它的出路)语法中使用它们:
self.importScripts( "/app/abc.js" );
Run Code Online (Sandbox Code Playgroud)
所以,我的问题是,我们如何使用新的导入模块语法与工人?
第二个问题是,importScripts从某个模块导入时导入的内容是什么?没有导出全局对象父项?
我正在尝试使用共享工作者来维护Web应用程序的所有窗口/选项卡的列表.因此,使用以下代码:
//lives in shared-worker.js
var connections=[];//this represents the list of all windows/tabs
onconnect=function(e){
connections.push(e.ports[0]);
};
Run Code Online (Sandbox Code Playgroud)
每次创建窗口时,都会与shared-worker.jsworker 建立连接,并且worker将与窗口的连接添加到connections列表中.
当用户关闭窗口时,它与共享工作程序的连接将过期,应从connections变量中删除.但我找不到任何可靠的方法来做到这一点.
查看规范,connections变量的对象似乎没有包含属性/函数来检查连接是否仍然存在.
可能吗?
同样,总体目标是拥有所有窗口/选项卡的列表.
编辑:一种方法是使共享工作者消息窗口并期待回复.如果共享工作者没有收到回复,那么它将认为该窗口已关闭.在我的实验中,这种方法并不可靠; 问题是没有办法判断一个窗口是关闭还是只是花了很长时间才能回复.
共享Web Workers旨在允许来自同一站点(源)的多个页面共享单个Web Worker.
但是,如果您只有一个窗口/选项卡并且您导航到同一站点上的另一个页面,那么我不清楚规范(或其他有关共享工作者的教程和信息)共享工作者是否会持久存在.
这对于来自共享工作者的WebSocket连接的情况最有用,该连接在网站导航时保持连接.例如,想象一下即使在网站导航时也会持续存在的股票代码或聊天区域(无需重新连接WebSocket).
web-worker ×10
javascript ×7
html5 ×4
angular ×1
drawimage ×1
ecmascript-6 ×1
html5-canvas ×1
import ×1
module ×1
performance ×1
transferable ×1
typescript ×1
webkit ×1
webpack ×1
websocket ×1