Blocklyに基づきビジュアルプログラミングの入門級の実例（三、VUE環境でBlocklyのコードを非同期的に処理するサンプル）

本章では、VUEのシンプルなサンプルで、BlocklyのBlockから生成コードを非同期的に実行する方法を説明しております。
Blocklyのコードをステップ毎に実行する時は、Interpreterライブラリをよく使っているんですけど、Interpreterライブラリを使いたくない場合は、JavaScriptのeval関数でBlocklyのコードを実行することも可能です。
evalは一般的に同期でソースコードを実行されているんで、非同期的に実行したい場合はどうしたらよいかについてのことを、以下のサンプルで説明して見ましょう。

#事前準備

##Blockly
公式サイト：https://developers.google.com/blockly/
Web版の資材：https://developers.google.com/blockly/guides/get-started/web#get_the_code

##VUE
https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js

#サンプル

##testblock.js
このファイルで、画面表示用のブロックを作成します
BlocklyのDevelopToolから生成することができます。

```#JavaScript
Blockly.Blocks['block_asyncplay'] = {
  init: function() {
    this.appendStatementInput("MUSIC")
        .setCheck(null)
        .setAlign(Blockly.ALIGN_RIGHT)
        .appendField("play");
    this.setInputsInline(true);
    this.setPreviousStatement(true, null);
    this.setNextStatement(true, null);
    this.setColour(120);
 this.setTooltip("");
 this.setHelpUrl("");
  }
};
Blockly.JavaScript['block_asyncplay'] = function(block) {
  var statements_music = Blockly.JavaScript.statementToCode(block, 'MUSIC');
  var code = "async function asyncplay() {\n" + statements_music + "\n}\n";
  return code;
};

Blockly.Blocks['block_play'] = {
  init: function() {
    this.appendDummyInput()
        .setAlign(Blockly.ALIGN_RIGHT)
        .appendField("play");
    this.setInputsInline(true);
    this.setPreviousStatement(true, "String");
    this.setNextStatement(true, "String");
    this.setColour(120);
    this.setTooltip("");
    this.setHelpUrl("");
  }
};
Blockly.JavaScript['block_play'] = function(block) {
	var code = "await play(1000);\n";
	return code;
};
```

##test01.html
画面にブロックを表示するためのHTMLファイルです。

```<html>
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js'></script><!-- 2019-01-25 https://cdnjs.com/libraries/vue -->

    <script src="../blockly-master/blockly_compressed.js"></script>
    <script src="../blockly-master/blocks_compressed.js"></script>
    <script src="../blockly-master/javascript_compressed.js"></script>
    <script src="../blockly-master/msg/js/en.js"></script>
    <script src="./testblock.js"></script>
<body>

<div id="vue_example"></div>

<script>
var vue_example = new Vue({
  el: '#vue_example',

  template: `<div>
  		<div width="600px" height="50px">
		    <button v-on:click="test()">test</button>
		</div>
    	<div width="600px" height="600px">
              <div id="blocklyDiv" style="height: 100%; width: 100%;"></div>
              <xml id="toolbox" ref="toolbox" style="display: none">
                <block type="block_asyncplay"></block>
                <block type="block_play"></block>
              </xml>
              <xml id="workbox" ref="workbox">
                <block type="block_asyncplay" id="id_block_asyncplay" x="10" y="30">
	                <statement name="MUSIC">
		                <block type="block_play" id="id_block_play_01">
			                <next>
				                <block type="block_play" id="id_block_play_02">
					                <next>
					                	<block type="block_play" id="id_block_play_03"></block>
					                </next>
				                </block>
			                </next>
		                </block>
	                </statement>
                </block>
              </xml>
    	</div>
    </div>`,

  data: {
    message: 'Hello Vue.js!',
  },
  mounted() {
      var workbox = this.$refs["workbox"];
      var options = {
        toolbox: toolbox,
        collapse: true,
        comments: true,
        disable: true,
        maxBlocks: Infinity,
        trashcan: true,
        horizontalLayout: false,
        toolboxPosition: 'start',
        css: true,
        rtl: false,
        scrollbars: true,
        sounds: true,
        oneBasedIndex: true,
        grid: {
          spacing: 20,
          length: 1,
          colour: '#888',
          snap: true
        }
      }

      /* Inject your workspace */
      this.workspace = Blockly.inject('blocklyDiv', options)
      //Workspaceに書かれたBlocksを表示
      Blockly.Xml.domToWorkspace(workbox, this.workspace);

  },
  methods: {
    test: function () {
    
      var dom = Blockly.Xml.workspaceToDom(this.workspace);
      console.log( Blockly.Xml.domToText(dom));
      
      var code = Blockly.JavaScript.workspaceToCode(this.workspace);
      console.log( code );
      
      eval(code);
      asyncplay();
      
	    async function play(waittime) {
			return new Promise((resolve, reject) => {
				console.log("play waittime:" + waittime);
				setTimeout(resolve, waittime, 'time signature');
			});
	    
		}
    },
	
  },
})
</script>
</body>
</html>
```

#実行結果

![実行結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229009/4168cbbe-a716-32bc-ce86-5bb0efb360e4.png)