share facebook facebook twitter menu hatena pocket slack

2017.07.10 MON

Javascriptの実行順序(Web Worker、非同期処理、イベント )

二神 暢彦

WRITTEN BY 二神 暢彦

cloudpack あら便利カレンダー 2017 16日目の記事です。

JavaScriptには非同期処理やイベント発火で実行されるもの、またWeb Workersを利用した別スレッドでの実行など記述した順序どおりではない実行タイミングのものがわりと多用されます。

そこでふと気になったのでそれぞれの実行順序ってどうなっているのか
Web Workersの別スレッドで実行された結果がどのタイミングで受取ったイベント発行されるのか気になったので
サンプルのコードを書いてざっくり調査してみました。

実行される処理

  1. Web Worker1での1つめの処理
  2. Web Worker2で2つめのループ処理
  3. Web Worker1で3つめのループ処理
  4. 非同期で実行される処理(setTimeout)
  5. べた書きでのループ処理1
  6. べた書きでのループ処理2
  7. ボタンクリックでのイベント発火

記述した順序は上に書いたとおりで試しています。

書いたコード

// メインのスクリプト
document.getElementById('btn')
    .addEventListener('click', () => console.info('button click fired!!!'));

document.getElementById('start')
    .addEventListener('click', () => {
        workerLog = function (e) {
            console.group();
            console.log(`%c${e.data} Worker onmessage fired!!!`, 'background: yellow; color:blue;');
        }

        let myWordker = new Worker('./worker.js');
        myWordker.onmessage = workerLog
        let myWordker2 = new Worker('./worker.js');
        myWordker2.onmessage = workerLog

        myWordker.postMessage("First Worker>>>");
        myWordker2.postMessage("Second Worker>>>");
        myWordker.postMessage("Third Worker>>>");

        setTimeout(() => {
            console.groupCollapsed();
            for (let i = 0; i < 10000; i++) {
                console.log('First Timeout>>>' + i);
            }
            console.groupEnd();
        }, 10)

        console.groupCollapsed();
        for (let i = 0; i < 10000; i++) {
            console.log('First Loop>>>' + i);
        }
        console.groupEnd();

        console.groupCollapsed();
        for (let i = 0; i < 10000; i++) {
            console.log('Second Loop>>>' + i);
        }
        console.groupEnd();
    })
// Worker
onmessage = function(e) {
    let ar = []
    // console.group();
    for(let i=0; i<10; i++) {
        ar.push(i)
        // console.log(e.data+i)
    }
    postMessage(e.data)
}

結果

べた書きで書いたループ処理の実行が2つとも完了しない限り、
Workerからのメッセージ受取イベントonmessageや、 非同期処理setTimeoutの実行は開始されませんでした。
またループ処理の途中で割り込み処理が入ることはないです。
クリックイベントに関してはメインのスレッドが完了後、イベントの発火が登録されていればsetTimeoutonmessageの処理よりも先に実行されました。

以下にサンプルコードをアップしています。
https://nobu222.github.io/WebWorker-sample/

元記事はこちら

Javascriptの実行順序(Web Worker、非同期処理、イベント )