从WebWorker同步获取数据?

时间:2017-03-27 04:35:16

标签: javascript locking web-worker synchronous webassembly

虽然我理解JavaScript本质上是单线程的,并且通常对这些事情不满意,但我想知道是否有任何办法让WebWorker等到主线程提供一些数据而不破坏调用堆栈WebWorker。

由于这是一个有趣的项目,我可以使用在旧浏览器上无法可靠运行的新技术和新东西,只要它们有效,我就不会介意深奥的黑客攻击。

我考虑过的其他一些解决方案:

  • 在循环中连续轮询LocalStorage,直到预定密钥上有数据。这似乎是有效的,因为其他线程的LocalStorage更新应该对当前线程可见,即使在循环中轮询,从所有discussions判断有关LocalStorage的线程安全性并让多个选项卡写入同一LocalStorage键。这种方法的缺点是它不是真的等待#34;即工作线程仍然消耗在LocalStorage上的全部CPU使用率。虽然LocalStorage通常使用锁实现,但是长时间不能持有LocalStorage锁(锁定在getItemsetItem返回后释放)。

  • ECMAScript 6 yield。这在这里不起作用,因为它需要调用堆栈中的所有函数(直到你想要屈服的地方)被标记为生成器函数。我想暂停我的WebWorker的地方有一个包含WebAssembly函数的调用堆栈,它不能被标记为生成器函数。

  • 索引资料。这不起作用,因为IndexedDB不支持同步请求。

我知道this类似的问题,但该问题专门讨论了onmessage事件,并在2012年yield和WebAssembly介绍之前提出了问题。

有没有办法以某种方式模拟WebWorker线程上的锁,或者其他方式,以便它等到某些数据可用?

1 个答案:

答案 0 :(得分:6)

修改请注意SharedArrayBufferdisabled by default in all major browsers(2018年1月5日)以回复Spectre

JavaScript SharedArrayBuffer听起来非常适合您:

  • 新技术:只是在1月的TC39会议上(ES2017及时)进入第4阶段
  • 无法在较旧的浏览器上可靠地运行(旧版本具有不同的API,或者没有可用的实现)
  • esoteric hack(similar to the C++ memory model
  • 工作原理

出于您的目的,您希望WebWorker等待数据可用。使用SharedArrayBuffer,您可以使用自旋循环(Atomics.load直到值更改)但最好使用Atomics.wait,直到其他工作人员向您发送Atomics.wake。后来的API受到Linux's futex的启发,如果您等待的价值无法使用,则不会不必要地旋转。

// Main program:
var w = new Worker("worker.js")
var sab = new SharedArrayBuffer(1024);
w.postMessage(sab);
var i = new Int32Array(sab);
// Maybe wait for worker.js to message back that it's ready through onmessage?
//
// Fill i with some data!
// ...
//
// Notify one worker, at location 0, with value 1.
Atomics.store(i, 0, 1);
Atomics.wake(i, 0, /* notify count */ 1);


// worker.js:
var sab;
var i;
onmessage = function (ev) {
    sab = ev.data;
    var i = new Int32Array(sab);
}
// Maybe tell the main program we're ready through postMessage?
//
// ...
// Wait until location 0 isn't value 0
Atomics.wait(i, 0, 0);

请记住:阻止主线程是一个坏主意!如果您这样做,您的网站将无法响应。你的问题是关于阻止一个工人,但读者可能有兴趣等待主线程。唐'!吨

非常相似且兼容的API eventually be available in WebAssemblyHere's an early draft proposal。当我说兼容时:我们希望WebAssembly能够使用与JavaScript相同的SharedArrayBuffer,并且两者都能够通过它无缝地进行通信。