WASMとWebワーカーのブラウザでの実行



郵便Running Go in the Browser with WASM and Web Workers 初登場Qvault .
私たちは最近、ブラウザ上で実行する方法に大きな変更を加えましたQvault そして、強化を説明したい.Webワーカーは、私たちが私たちを保持していた深刻なブラウザ関連のコーディングの問題のいくつかを解決することができた理由です.この記事を続編Running Go in the Browser with Web Assembly .
我々の最新コースを発表している間.Big-O Algorithms , コードがまだ実行されている間、コンソール出力を印刷する方法が必要でした.ブラウザで計算的に高価なアルゴリズムを実行するとき、私たちは問題に出くわしましたブラウザは、それが出力の新しい行をレンダリングすることができないようにboggedダウンします.我々は、Web労働者を実装することを決め、彼らは手際よく問題を解決した.

問題


古いqvaultでは、コンソール出力はすべて一度に印刷されました.プログラムが実行され、出力が表示されました.特に速度のアルゴリズムを最適化しようとするとき、何かが印刷されるとき、それがしばしば見るのに役に立つので、我々はこれが理想的であるということを発見しました.
たとえば、このコードは、すべての出力を一度に出力するために使用します.
package main

import (
    "fmt"
)

func main(){
    const max = 100000000
    for i := 0; i < max; i++{
        if i % (max/10) == 0{
            fmt.Println(i)
        }
    }
}

Web労働者を追加するので、現在適切に実行時に各番号を印刷します.あなた自身のために見ることができますplayground here .

ウェブワーカーは何ですか?


Web Workers are a simple means for web content to run scripts in background threads.

Mozilla


言い換えれば、私たちが最終的にJavaScriptの単一スレッドのクラッチから解放するための方法です!私たちは高価なタスクを実行の別のスレッドに追い詰めることができます.これを行うと、ブラウザが画面上の更新をレンダリングするには無料です.

どのように動作する-労働者


ご存知のように、エディタでコードをサーバーでWASMにコンパイルします.あなたがその部分について興味があるならば、あなたは我々にそれを読むことができますprevious post. コードがWebアセンブリにコンパイルされると、実行用にフロントエンドに戻されます.
Webワーカーを実行するには、作業者を定義するスクリプトが必要です.JavaScriptファイルだけです.
addEventListener('message', async (e) => {
    // initialize the Go WASM glue
    const go = new self.Go();

    // e.data contains the code from the main thread
    const result = await WebAssembly.instantiate(e.data, go.importObject);

    // hijack the console.log function to capture stdout
    let oldLog = console.log;
    // send each line of output to the main thread
    console.log = (line) => { postMessage({
        message: line
    }); };

    // run the code
    await go.run(result.instance);
    console.log = oldLog;

    // tell the main thread we are done
    postMessage({
        done: true
    });
}, false);

労働者は、主な糸を聞くことによって通信するmessage イベント、そしてデータをpostMessage 関数.
注意:私はwasmrage execを省略しました.作業者がGOコードを実行するために必要なJSファイルがインストールされている場合は、マシン上で見つけることができます.
cat $(go env GOROOT)/misc/wasm/wasm_exec.js

主なスレッド


コンパイルされたWebアセンブリを実行できるような作業ファイルを持っているので、メインスレッドがどのように働くかを見てみましょう.私はいくつかのヘルパー機能をエクスポートするES 6モジュールを構築しました.
export function getWorker(lang) {
  return {
    webWorker: new window.Worker(`/${lang}_worker.js`),
    lang
  };
}

export function useWorker(worker, params, callback) {
  const promise = new Promise((resolve, reject) => {
    worker.webWorker.onmessage = (event) => {
      if (event.data.done) {
        resolve();
        return;
      }
      if (event.data.error) {
        reject(event.data.error);
        return;
      }
      callback(event.data.message);
    };
  });
  worker.webWorker.postMessage(params);
  return promise;
}

export function terminateWorker(worker) {
  worker.webWorker.terminate();
}
ページ読み込み時に新しいWebワーカーを作成しますgetWorker . ユーザーがコードを実行すると、コードをuseWorker . コードエディターから離れて移動すると、使用者をクリーンアップできますterminateWorker .
The useWorker 機能はポスト面白い部分です.それはgetWorker , という物体params これは、ワーカー(コンパイルされたワームが含まれている)と、作業者がジョブで終了したときに実行するコールバック関数に渡されます.
例えば、Vueアプリでは以下の関数を使用します.
this.output = [];
this.isLoading = true;
const wasm = await compileGo(this.code);
await useWorker(this.worker, wasm, (data) => {
  this.output.push(data); 
});
this.isLoading = false;
なぜならthis.output Vueインスタンスでは、Webワーカーからデータを受け取るたびに、新しい出力がコンソールに印刷されます.

読書ありがとう!


あなたがどんな質問またはコメントをするならば、さえずりの上で我々について来てください
取るcoding courses on our new platform
Subscribe より多くのプログラミング記事のための我々の会報へ