36

HTML5でWebワーカーを次のように使用できます。

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

しかし、なぜこのような関数を呼び出せないのでしょうか。

var worker = new Worker(function(){
    //do something
});
4

7 に答える 7

28

これがWebワーカーの設計方法です。独自の外部JSファイルと、そのファイルによって初期化された独自の環境が必要です。マルチスレッドの競合のため、通常のグローバルJSスペースと環境を共有することはできません。

Webワーカーがグローバル変数への直接アクセスを許可されない理由の1つは、2つの環境間でスレッドの同期が必要になるためです。これは、利用できるものではありません(そして、事態を非常に複雑にします)。Webワーカーが独自の個別のグローバル変数を持っている場合、メインJSスレッドと適切に同期されているメッセージングキューを経由する場合を除いて、メインJSスレッドを混乱させることはできません。

おそらくいつか、より高度なJSプログラマーは、従来のスレッド同期技術を使用して共通変数へのアクセスを共有できるようになりますが、今のところ、2つのスレッド間のすべての通信はメッセージキューを経由する必要があり、WebワーカーはメインのJavascriptスレッドにアクセスできません。環境。

于 2012-07-06T02:19:20.153 に答える
10

この質問は以前に尋ねられましたが、何らかの理由で、OPはそれを削除することを決定しました。
関数からWebワーカーを作成するメソッドが必要な場合に備えて、回答を再投稿します。


この投稿では、任意の文字列からWebワーカーを作成する3つの方法を紹介しました。この回答では、すべての環境でサポートされているため、3番目の方法を使用しています。

ヘルパーファイルが必要です:

// Worker-helper.js
self.onmessage = function(e) {
    self.onmessage = null; // Clean-up
    eval(e.data);
};

実際のワーカーでは、このヘルパーファイルは次のように使用されます。

// Create a Web Worker from a function, which fully runs in the scope of a new
//    Worker
function spawnWorker(func) {
    // Stringify the code. Example:  (function(){/*logic*/}).call(self);
    var code = '(' + func + ').call(self);';
    var worker = new Worker('Worker-helper.js');
    // Initialise worker
    worker.postMessage(code);
    return worker;
}

var worker = spawnWorker(function() {
    // This function runs in the context of a separate Worker
    self.onmessage = function(e) {
        // Example: Throw any messages back
        self.postMessage(e.data);
    };
    // etc..
});
worker.onmessage = function() {
    // logic ...
};
worker.postMessage('Example');

スコープは厳密に分離されていることに注意してください。worker.postMessage変数は、とを使用してのみ受け渡しできますworker.onmessage。すべてのメッセージは構造化されたクローンです。

于 2012-07-08T09:05:22.067 に答える
3

この答えは少し遅いかもしれませんが、私はWebワーカーの使用を簡素化するためにライブラリを作成し、OPのニーズに合うかもしれません。それをチェックしてください:https ://github.com/derekchiang/simple-worker

それはあなたが次のようなことをすることを可能にします:

SimpleWorker.run({
  func: intensiveFunction,
  args: [123456],
  success: function(res) {
    // do whatever you want
  },
  error: function(err) {
    // do whatever you want
  }
})
于 2013-07-14T03:13:56.150 に答える
2

WebWorkers Essentials

WebWorkersは独立したスレッドで実行されるため、WebWorkersを宣言するメインスレッド(およびその逆)にアクセスすることはできません。結果のスコープは分離され、制限されます。そのため、たとえば、ワーカー内からDOMにアクセスすることはできません。


WebWorkersとのコミュニケーション

スレッド間の通信が必要なため、それを実現するメカニズムがあります。標準の通信メカニズムは、worker.postMessage()関数と worker.onMessage()、イベントハンドラーを使用したメッセージを介したものです。

sharedArrayBuffersを含む、より高度な手法が利用可能ですが、それらをカバーすることは私の目的ではありません。それらに興味がある場合は、こちらをお読みください


スレッド関数

それが標準が私たちにもたらすものです。ただし、ES6は、オンデマンドの呼び出し可能なスレッド関数を実装するのに十分なツールを提供します。

Blobからワーカーを構築でき、関数を( URL.createObjectURLを使用して)それに変換できるため、メッセージを処理し、自然なものを取得するには、両方のスレッドに何らかの通信レイヤーを実装するだけで済みます。インタラクション。

もちろん、すべてが非同期で発生することを考えると、約束はあなたの友達です。

この理論を適用すると、説明するシナリオを簡単に実装できます。


私の個人的なアプローチ:ParallelFunction

私は最近、あなたが説明したことを正確に実行する小さなライブラリを実装して公開しました。2KB未満(縮小)。

これはParallelFunctionと呼ばれ、 githubnpm、およびいくつかのCDNで利用できます。

あなたが見ることができるように、それはあなたの要求と完全に一致します:

// Your function...
let calculatePi = new ParallelFunction( function(n){
    // n determines the precision , and in consequence 
    // the computing time to complete      
    var v = 0;
    for(let i=1; i<=n; i+=4) v += ( 1/i ) - ( 1/(i+2) );
    return 4*v;
});

// Your async call...
calculatePi(1000000).then( r=> console.log(r) );

// if you are inside an async function you can use await...
( async function(){    
    let result = await calculatePi(1000000);
    console.log( result );
})()

// once you are done with it...
calculatePi.destroy();

初期化後、必要な回数だけ関数を呼び出すことができます。関数の実行が終了すると、Promiseが返され、解決されます。

ちなみに、他にもたくさんのライブラリがあります。

于 2018-04-24T02:45:49.547 に答える
1

私の小さなプラグインを使用するだけですhttps://github.com/zevero/worker-create

そして、やります

var worker_url = Worker.create(function(e){
  self.postMessage('Example post from Worker'); //your code here
});
var worker = new Worker(worker_url);
于 2015-10-18T12:51:53.450 に答える
1

これは最適ではなく、コメントで言及されていますが、ブラウザーがWebワーカーのblobURLをサポートしている場合は、外部ファイルは必要ありません。HTML5Rocksは私のコードのインスピレーションでした:

function sample(e)
{
    postMessage(sample_dependency());
}

function sample_dependency()
{
    return "BlobURLs rock!";
}

var blob = new Blob(["onmessage = " + sample + "\n" + sample_dependency]);
var blobURL = window.URL.createObjectURL(blob);
var worker = new Worker(blobURL);

worker.onmessage = function(e)
{
    console.log(e.data);
};

worker.postMessage("");

警告:

  • ブロブワーカーは相対URLを正常に使用しません。HTML5Rocksリンクはこれをカバーしていますが、元の質問の一部ではありませんでした。

  • 人々は、WebワーカーでBlobURLを使用する際の問題を報告しています。IE11(FCUに同梱されているものは何でも)、MS Edge 41.16299(Fall Creator's Update)、Firefox 57、およびChrome62で試してみました。Safariのサポートに関する手がかりはありません。私がテストしたものはうまくいきました。

  • Blobコンストラクター呼び出しの「sample」および「sample_dependency」参照は、暗黙的にFunction.prototype.toString()assample.toString()およびを呼び出します。これは、およびを呼び出すこととsample_dependency.toString()は大きく異なります。toString(sample)toString(sample_dependency)

これは、追加のファイルを要求せずにWebワーカーを使用する方法を検索したときに発生した最初のstackoverflowであるために投稿されました。

Zeveroの回答を見てみると、彼のリポジトリのコードは似ているように見えます。クリーンなラッパーを好む場合、これはほぼ彼のコードが行うことです。

最後に-私はここでは初心者なので、すべての修正を歓迎します。

于 2017-11-30T20:46:55.433 に答える
0

設計上、Webワーカーはマルチスレッドであり、javascriptはシングルスレッドです" *"複数のスクリプトを同時に実行することはできません。

参照:http ://www.html5rocks.com/en/tutorials/workers/basics/

于 2012-07-06T02:20:21.013 に答える