Membuat dan menjalankan JavaScript

Aplikasi Blockly sering menghasilkan JavaScript sebagai bahasa outputnya, umumnya untuk dijalankan dalam halaman web (mungkin sama, atau WebView tersemat). Seperti generator lainnya, langkah pertama adalah menyertakan generator JavaScript.

import {javascriptGenerator} from 'blockly/javascript';

Untuk membuat JavaScript dari ruang kerja, panggil:

javascriptGenerator.addReservedWords('code');
var code = javascriptGenerator.workspaceToCode(workspace);

Kode yang dihasilkan dapat dijalankan langsung di halaman web tujuan:

try {
  eval(code);
} catch (e) {
  alert(e);
}

Pada dasarnya, cuplikan di atas hanya menghasilkan kode dan mengevaluasinya. Namun, ada beberapa peningkatan. Salah satu peningkatannya adalah eval digabungkan dalam try/catch sehingga error runtime terlihat, bukan gagal secara diam-diam. Penyempurnaan lainnya adalah code ditambahkan ke daftar kata yang dicadangkan sehingga jika kode pengguna berisi variabel dengan nama tersebut, variabel tersebut akan diganti namanya secara otomatis, bukan bertabrakan. Setiap variabel lokal harus disediakan dengan cara ini.

Blok Sorotan

Menandai blok yang sedang dieksekusi saat kode berjalan membantu pengguna memahami perilaku program mereka. Penandaan dapat dilakukan pada tingkat pernyataan demi pernyataan dengan menetapkan STATEMENT_PREFIX sebelum membuat kode JavaScript:

javascriptGenerator.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
javascriptGenerator.addReservedWords('highlightBlock');

Tentukan highlightBlock untuk menandai blok di ruang kerja.

function highlightBlock(id) {
  workspace.highlightBlock(id);
}

Hal ini menyebabkan pernyataan highlightBlock('123'); ditambahkan sebelum setiap pernyataan, dengan 123 adalah nomor seri blok yang akan ditandai.

Loop Tanpa Batas

Meskipun kode yang dihasilkan dijamin selalu benar secara sintaksis, kode tersebut dapat berisi loop tanpa batas. Karena menyelesaikan Masalah penghentian berada di luar cakupan Blockly (!), pendekatan terbaik untuk menangani kasus ini adalah mempertahankan penghitung dan menguranginya setiap kali iterasi dilakukan. Untuk melakukannya, cukup tetapkan javascriptGenerator.INFINITE_LOOP_TRAP ke cuplikan kode yang akan disisipkan ke dalam setiap loop dan setiap fungsi. Berikut adalah contohnya:

window.LoopTrap = 1000;
javascriptGenerator.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = javascriptGenerator.workspaceToCode(workspace);

Contoh

Berikut adalah demo langsung untuk membuat dan menjalankan JavaScript.

JS-Interpreter

Jika Anda serius ingin menjalankan blok pengguna dengan benar, maka project JS-Interpreter adalah pilihan yang tepat. Project ini terpisah dari Blockly, tetapi ditulis secara khusus untuk Blockly.

  • Jalankan kode dengan kecepatan apa pun.
  • Menjeda/melanjutkan/melangkahi eksekusi.
  • Menandai blok saat dieksekusi.
  • Sepenuhnya terisolasi dari JavaScript browser.

Menjalankan Penafsir

Pertama, download JS-Interpreter dari GitHub:

Download File ZIP Mendownload TAR Ball Lihat di GitHub

Kemudian, tambahkan ke halaman Anda:

<script src="acorn_interpreter.js"></script>

Metode paling sederhana untuk memanggilnya adalah dengan membuat JavaScript, membuat interpretor, dan menjalankan kode:

var code = javascriptGenerator.workspaceToCode(workspace);
var myInterpreter = new Interpreter(code);
myInterpreter.run();

Menjalankan Penafsir

Untuk menjalankan kode lebih lambat, atau dengan cara yang lebih terkontrol, ganti panggilan ke run dengan loop yang melakukan langkah (dalam hal ini satu langkah setiap 10 md):

function nextStep() {
  if (myInterpreter.step()) {
    setTimeout(nextStep, 10);
  }
}
nextStep();

Perhatikan bahwa setiap langkah bukanlah baris atau blok, melainkan unit semantik dalam JavaScript, yang mungkin sangat terperinci.

Menambahkan API

JS-Interpreter adalah sandbox yang sepenuhnya terisolasi dari browser. Setiap blok yang melakukan tindakan dengan dunia luar memerlukan API yang ditambahkan ke interpretator. Untuk deskripsi lengkap, lihat dokumentasi Penafsir JS. Namun, untuk memulai, berikut adalah API yang diperlukan untuk mendukung blok pemberitahuan dan perintah:

function initApi(interpreter, globalObject) {
  // Add an API function for the alert() block.
  var wrapper = function(text) {
    return alert(arguments.length ? text : '');
  };
  interpreter.setProperty(globalObject, 'alert',
      interpreter.createNativeFunction(wrapper));

  // Add an API function for the prompt() block.
  wrapper = function(text) {
    return prompt(text);
  };
  interpreter.setProperty(globalObject, 'prompt',
      interpreter.createNativeFunction(wrapper));
}

Kemudian, ubah inisialisasi penafsir untuk meneruskan fungsi initApi:

var myInterpreter = new Interpreter(code, initApi);

Blok pemberitahuan dan perintah adalah dua-satunya blok dalam kumpulan blok default yang memerlukan API kustom untuk penafsir.

Menghubungkan highlightBlock()

Saat berjalan di JS-Interpreter, highlightBlock() harus segera dieksekusi, di luar sandbox, saat pengguna melakukan langkah-langkah dalam program. Untuk melakukannya, buat fungsi wrapper highlightBlock() untuk mengambil argumen fungsi, dan daftarkan sebagai fungsi native.

function initApi(interpreter, globalObject) {
  // Add an API function for highlighting blocks.
  var wrapper = function(id) {
    return workspace.highlightBlock(id);
  };
  interpreter.setProperty(globalObject, 'highlightBlock',
      interpreter.createNativeFunction(wrapper));
}

Aplikasi yang lebih canggih mungkin ingin berulang kali menjalankan langkah tanpa jeda hingga perintah sorotan tercapai, lalu dijeda. Strategi ini menyimulasikan eksekusi baris demi baris. Contoh di bawah menggunakan pendekatan ini.

Contoh Penafsir JS

Berikut adalah demo langsung untuk menafsirkan JavaScript langkah demi langkah. Selain itu, demo ini menyertakan blok tunggu, contoh yang baik untuk digunakan untuk perilaku asinkron lainnya (misalnya, ucapan atau audio, input pengguna).