Help us understand the problem. What is going on with this article?

javascriptのWebWorkerを使ってみた

More than 1 year has passed since last update.

WebWorkerとは?

初心者です。

WebWorkerとはjavascriptでマルチスレッドを行うための仕組みです。
マルチスレッドとは、複数の処理を同時に行うことです。

例えば、描画処理などで
 ・データ取得処理
 ・取得したデータの描画処理
を同時に行うと描画が滞りなく行われます。

処理を同時に行わない場合は、

 データ取得 → 描画 → データ取得 → 描画 → ・・・

となり、データ取得の度に描画が止まります。これを

 処理A :データ取得 → データ取得 → ・・・
 処理B :描画    → 描画    → ・・・

の様に処理A、Bを同時に行ってスムーズに描画するという機能です。
(あくまで一例。処理が軽い場合は普通に記述して問題ない)

非同期処理は?

javascriptは非同期処理でpromiseなどありますが、
あれは処理の順番を変えているだけで同時に処理を行うものではありません(でした)。

 非同期処理 = 並行して処理を行ってくれる

と考えがちですが、javascriptは(原則)違います。

概要とか特徴

概要
 ・メインスレッド(main.js) ←メイン処理
 ・サブスレッド(doWork.js) ←main.jsから呼び出して並行して処理

特徴
 ・処理ごとにファイルを分ける。
 ・データのやり取りはJSON等で行う。他にもある。
 ・サブスレッド(doWork.js)から、DOM操作(タグ編集とか)は出来ない。
   window.document.form.****とかはNG
 ・jQueryもダメ($ajaxとか)。レスポンスには適用できる。
 ・通信は、XMLHttpRequestやfetchなどで出来る。

基本的な使い方

 同時進行で行う処理を、doWorker.jsに記述する。
 main.jsでdoWorker.jsを呼び出す。

index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
  <script src="js/main.js"></script>
</head>
<body>
    <input type="text"   id="idParamPost"    value="送信メッセージ">
    <input type="text"   id="idParamReceive" value="">
    <input type="button" id="idBtnDoPost"    value="送信">
</body>
</html>
main.js
//送信
$(document).on('click', '#idBtnDoPost', function(){

  //workerオブジェクト
  var worker = new Worker('js/doWork.js');

  //処理結果、受信イベント
  worker.addEventListener('message', function(e) {
    $("#idParamReceive").val(e.data);
  }, false);

  //処理命令
  worker.postMessage($("#idParamPost").val());
});
doWork.js
//worker
self.addEventListener('message', function(e) {

  //何か同時進行で行う処理

  //処理結果を送信
  self.postMessage(e.data);
}, false);

注意
 main.jsのコードの書き順は決まっている様なので、この通りに書く。

マルチスレッドな使い方

 上記では、いまいちWebWorkerの有難味が分からない。
 これが便利だと思えるのは、(繰り返しになるが)下記の様な描画処理である。
 同時に行わない場合は、データ取得の度に描画が止まる。
 下記の例では受け取る配列(aryJSON)は1つであるが、受信するバッファを複数にしたり、
 バッファの要素数を調節したりと、ケースによる調整は必要である。

main.js
//処理開始
$(document).on('click', '#idBtnDoPost', function(){

  //非同期で受信するデータ
  var aryJSON = [];

  //workerオブジェクト
  var worker = new Worker('js/doWork.js');

  //受信イベント
  worker.addEventListener('message', function(e) {
    aryJSON = e.data;  //処理ループ内で使用するデータ
  }, false);

  //処理ループ
  while(true){

    //非同期でデータ取得
    worker.postMessage($("#idParamPost").val());

    //取得したデータ表示
    viewJSON(aryJSON);
  }

});

豆知識

 jsonデータを送受信する場合は、下記の様にパースする。

doWork.js
//worker
self.addEventListener('message', function(e) {
  //メッセージ送信
  self.postMessage(JSON.parse(e.data));  //JSONにパース
}, false);
qiiChan
紆余曲折合って、福岡でフリープログラマーやってます^^ ツイッター:https://twitter.com/hrlArZUXxmd0Zo7
http://ryutai.ninja-web.net/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした