FrontEnd

Go WebAssemblyでPromiseを使って非同期化してみた

投稿日:

はじめに

先日WebAssemblyに入門して、実際に以下のチュートリアルを進めながら、WebAssemblyを使用してブラウザ上でGoを動かすことができました。

GoでWebAssemblyに触れよう
https://golangtokyo.github.io/codelab/go-webassembly/

ただ、このチュートリアルをベースにGoの処理を書いていくと気が付くのですが、Goの処理が完了するまでJavaScriptの処理が止まってしまいます。そこで、Goを非同期化させたいと思います。
もし、初めてGoでのWebassemblyに触れる方は、初めに上記のチュートリアルに触れておくことをおすすめします。

Go WebAssemblyで非同期化のコード

js.FuncOf() で定義した関数が、JS側から呼び出されると、Go側での処理が完了するまで、JSのイベントループはブロックされます。これを回避するためには、Go側の関数で新たなgoroutineを開始する必要があります。今回は画像をWeb上からダウンロードしてブラウザ上に表示するというサンプルコードで説明します。

まずはGo側です。

このように、goroutineで処理することによって、JavaScriptのイベントループを止めることなく、非同期処理を行うことができます。
ダウンロードした画像をJavaScript側に渡すため、JavaScript側から第二引数にコールバック用の関数を渡してもらうようにしています。この関数を実行するには Invoke()関数を使用します。
Invoke()関数に引数を渡すと、そのままJavaScriptに渡すことができるので、サンプルでは callback.Invoke(outputBytes) という形でダウンロードしたデータを渡しています。

次に、HTML側です。

先ほどgo側で定義したように、download関数の第一引数に画像のURL、第二引数にはコールバック用の関数を渡します。コールバック用の関数では、第一引数に画像データが渡ってくるので、これを受け取ってimgタグとして表示しています。

このように、goroutineを使うことでJavaScriptと非同期で連携することができます。JavaScript側からのインターフェイスとしては、通常の非同期処理と同じであることも分かりました。それでは、この非同期化処理をいよいよPromise化したいと思います。

Promise化する

先ほどのコードをPromise化するため、download関数を次のように変更します。

ポイントを紹介します。

  • js.Global().Get("Promise").New(handler) でPromiseを生成することができます。これは、JavaScriptで new Promise(handler) を実行しているのと全く同じです。
  • handlerは jsFuncOf() で生成したJavaScriptの関数を渡します。
  • handlerが呼び出されると、通常のPromiseと同じように、第一引数にresolve、第二引数にrejectが渡されるので、非同期処理後にコールバックすることができます。

最後に、JavaScript側をPromiseに対応したコードに変更します。

画像を一気にダウンロードして、全て完了したら「ダウンロード完了」と表示するようにしています。
download(url) が、Go側で生成されたPromiseを返すので、thenやawaitを使うことができます。

おまけ

ダウンロードしたデータはGoでは []byte 型になりますが、これをそのままJavaScriptが側に渡すと InvalidValueエラーとなります。そこで、 js.CopyBytesToJS() 関数を使って、 []byte から Uint8Array に変換する必要がありました。
また、 js.CopyBytesToJS() の引数には、コピー先の Uint8Array を渡す必要があるため、あらかじめ空の Uint8Array を渡しています。
ちなみに、これとは逆の変換をするには、 js.CopyBytesToGo() を使い、JavaScriptの Uint8Array[]byte に変換することができます。

さいごに

GoでWebassemblyを使うユースケースがあまり思い浮かばないのですが、今後のアップデートでもっと用途が広がるかもしれません。今はまだ局所的な組み込みが現実的なのかなと思いました。

おすすめ書籍

改訂2版 みんなのGo言語 スターティングGo言語 (CodeZine BOOKS)

blog-page_footer_336




blog-page_footer_336




-FrontEnd
-, ,

執筆者:


comment

メールアドレスが公開されることはありません。

CAPTCHA


関連記事

Vue on Rails で作ったアプリを振り返ってみる

1 はじめに2 全体的なこと2.1 ディレクトリ構成2.2 CSSフレームワーク2.3 Capistranoでのデプロイ3 axiosのラッパー4 Vuex4.1 ログインの状態管理5 Router6 ...

Vue.jsでWebアプリケーションを作る〜Vue.jsの基礎〜

1 はじめに1.1 Vue.jsとは1.2 インストール1.3 Vueアプリケーションを作る2 データを表示する2.1 文字列を表示する2.2 HTMLで表示する3 属性を指定する3.1 インラインス ...

vuex-module-decoratorsとTypeScriptでvuexをスマートに書く

1 はじめに2 導入3 どのように記述するか3.1 初めに3.2 state3.3 mutation3.4 action3.5 getter3.6 async MutationAction3.7 Dy ...

Vue.jsとRailsでTODOアプリのチュートリアルみたいなものを作ってみた【2018.03.24】

1 はじめに1.1 作るもの1.2 前提条件、及び環境1.3 Webpack について2 準備2.1 Rails + Vue.jsのプロジェクトを作成する2.2 Vue.jsの表示確認2.3 devサ ...

svelte

Svelteのチュートリアルをやってみた

1 はじめに2 Svelteとは?2.1 Svelteの特徴2.2 Write less code2.3 No Virtual DOM2.4 Truly reactive3 Svelteのシンタックス ...

フォロー

blog-page_side_responsive

2021年11月
 123456
78910111213
14151617181920
21222324252627
282930  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。