2017-03-27 13 views
2

私はJavaScriptは、本質的にシングルスレッドであり、一般的にいくつかのデータは、メインスレッドから利用可能になるまでのコールスタックを破壊せずに待つようにWebWorkerを取得する方法があれば、私は疑問に思ってそのようなことによりしかめ面を理解しながらWebWorker。WebWorkerから同期してデータを取得しますか?

これは楽しいプロジェクトのためにあるように、私は確実に古いブラウザでは動作しません、と私は限り、彼らは仕事として難解なハックを気にしない新技術やものを使用することができます。

私が考えているいくつかの他のソリューション:データが所定のキーであるまでループで

  • 連続世論調査のlocalStorage。これは、LocalStorageのスレッドセーフに関するすべてのdiscussionsから判断し、同じLocalStorageキーに複数のタブを書き込むことによって、ループ内でポーリングされても、他のスレッドによるLocalStorageの更新を現在のスレッドで見ることができるからです。このアプローチの欠点は、実際には「待機」していない、つまりワーカースレッドがLocalStorageでCPU使用率を完全に消費していることです。 LocalStorageは通常ロックで実装されますが、長期間LocalStorageロックを保持することはできません(ロックはgetItemまたはsetItemが返された後で解放されます)。

  • のECMAScript 6 yield。これは、呼び出しスタック内のすべての関数(生成したい場所がジェネレータ関数としてマークされるまで)を必要とするため、ここでは機能しません。 WebWorkerを一時停止したい場所に、WebAssembly関数を含むコールスタックがあります。この関数はジェネレータ関数としてマークすることはできません。

  • IndexedDB。 IndexedDBは同期要求をサポートしていないため、これは機能しません。

私はthis同様の問題を認識していますが、その質問には、具体的onmessageイベントについて語っとyieldとWebAssemblyが導入される前、2012年に頼まれました。

WebWorkerスレッドのロックを何らかの形でシミュレートする方法はありますか?そうでなければ、データが利用できるようになるまで待つ方法はありますか?

+0

タイトルは、WebWorkerから同期的にデータを取得するよう求めていますが、WebWorkerがいわゆるメインからどのようにデータを取得できるかを質問しています。 –

+0

私はこの質問の表現に問題があるとは思わない。 「from」の意味は、「WebWorker」を場所または人/オブジェクトとして使用するかどうかによって異なります。タイトルは「WebWorker」を場所として使用します。 「遠くから見る」または「家からのコンテストに参加する」.WebWorkerにあるコードが何かをやろうとしている(この場合はデータを取得する)。あなたはオブジェクトとして "WebWorker"を使用しています。 "瓶からクッキーを取る"、エージェント/オブジェクトには、取得したいものがあります。私は「WebWorkerデータを同期して取得する」と書いたことがあります。あなたの質問をしたいと思ったら。 – Bernard

+0

right ...レッスンありがとう...非同期タスクを同期して実行しないでください –

答えて

4

のJavaScriptのSharedArrayBufferはあなたのために完璧にフィットのように聞こえる:

  • 新しい技術を:はちょうど
  • が確実に古いで実行されません(ES2017のための時間で)1月のTC39会議で4をステージに移動しましたブラウザ(旧バージョンが異なるAPIを持っていない、または利用可能な実装)
  • 難解なハック(similar to the C++ memory model
  • 作品

目的のために、データが利用できるようになるまでWebWorkerを待機させたいとします。 SharedArrayBufferを使用すると、スピンループ(値が変更されるまでAtomics.load)を使用できますが、他のワーカーがAtomics.wakeを送信するまでAtomics.waitを使用する方が良いでしょう。この後の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 WebAssemblyです。 Here's an early draft proposal。私は互換性があると言います:WebAssemblyはJavaScriptと同じようにSharedArrayBufferを使用でき、両方ともシームレスに通信できることが期待されます。

+0

これは有望です。そして、MVPが1か月も前にリリースされたWebAssemblyよりも新しいものです。 – Bernard

関連する問題