【scratch-vm応用講座】スクラッチの拡張機能でもasync/await構文を使う方法
※ 当ページには【広告/PR】を含む場合があります。
2021/12/12

スクラッチ3.0の自作エクステンションの作成に慣れてくると、色んなライブラリを読み込んでみたくなる時があります。
しかし残念ながらScratch-gui(正確にはScratch-vm)のデフォルトではjavascriptの非同期処理を扱う
でもご安心ください。
今回はスクラッチに非同期処理も行わせるコード修正の方法を説明していこうと思います。
スクラッチではasync/awaitが呼び出せない問題
Scratch-guiを使って拡張機能をいじっていくとき、何気なく
index.js:68 Uncaught ReferenceError: regeneratorRuntime is not defined
at index.js:68
at index.js:69
at Object../node_modules/scratch-vm/src/extensions/*****/index.js (index.js:78)
at __webpack_require__ (bootstrap:84)
at Object.******** (extension-manager.js:19)
at ExtensionManager.loadExtensionURL (extension-manager.js:153)
at ExtensionLibrary.handleItemSelect (extension-library.jsx:43)
at Object.wrapper [as onItemSelected] (index.js:550)
at LibraryComponent.handleSelect (library.jsx:68)
at Object.wrapper [as onSelect] (index.js:550)
原因を調べていくと、スクラッチというよりは
ではどうやってスクラッチからでも非同期処理を使えるようにするのかを解決策を解説していきましょう。
Babelランタイムの追加
まずはscratch-vmに潜って、足りていないbabel関連のランタイムを追加しましょう。
$ cd scratch-vm
$ yarn add @babel/runtime @babel/plugin-transform-runtime -D
これで準備完了です。
あとはこれをscratch-vmのエンドポイントとなっている
virtual-machine.js
//👇とりあえずコードの冒頭に二行を追加
require('core-js');
require('regenerator-runtime/runtime');
//...以下略
これだけでスクラッチでもasync/await構文を利用できるようになりました。
動作確認
せっかくなので簡単なasync/await構文を試せるだけの拡張機能を作って、動作してるか確認してみましょう。
拡張機能の作成手順は以前詳しく解説していた記事のほうを参考にしてください。
エクステンションの自作の手順に従い、以下の
index.js
const ArgumentType = require('../../extension-support/argument-type');
const BlockType = require('../../extension-support/block-type');
const Cast = require('../../util/cast');
const log = require('../../util/log');
class Scratch3AsyncTest {
constructor (runtime) {
this.runtime = runtime;
}
getInfo () {
return {
id: 'asynctest',
name: 'Debug for testing Async/Await',
blocks: [
{
opcode: 'testAsync',
text: 'Async/Await tester',
blockType: BlockType.COMMAND
}
],
menus: {
}
};
}
//👇await出来ようにPromiseの関数を定義
myFirstPromise(message) {
console.log('一秒遅延しています...');
return new Promise(resolve => {
setTimeout(() => {
resolve(message);
}, 1000);
})
}
//👇クラス内にasyncメンバ関数を定義
async myFirstAsync() {
const result = await this.myFirstPromise('はじめてのAsync/Awaitへようこそ!');
return result;
}
testAsync () {
//👇スクラッチブロックからでもasync関数が呼び出せるようになる
this.myFirstAsync().then(result => {
console.log(result);
});
}
}
module.exports = Scratch3AsyncTest;
以下のように作成したエクステンションのブロックをクリックするたびにブラウザのデバッグコンソールから表示できてるようならば成功です!

まとめ
今回はScratch3.0でもasync/awaitとPromise関数が使えるように、Babelに不足していたランタイムを自分で補う方法を簡単に解説していきました。
今日日、既に非同期処理のライブラリも増えてきていますので、このやり方を知っておくとスクラッチアプリの応用の幅がもっと広がると考えます。