Membuat dan Menjalankan JavaScript

Aplikasi yang bloknya 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 dieksekusi 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 penyempurnaan. Salah satu penyempurnaannya adalah bahwa evaluasi ini digabungkan dalam try/catch sehingga error runtime terlihat, bukan gagal secara diam-diam. Peningkatan lainnya adalah code ditambahkan ke daftar kata yang dicadangkan, sehingga jika kode pengguna berisi variabel untuk nama tersebut, nama tersebut akan otomatis diganti namanya, bukan bentrok. Setiap variabel lokal harus dipertahankan dengan cara ini.

Blok Sorotan

Menyoroti blok yang sedang dieksekusi saat kode berjalan akan membantu pengguna memahami perilaku program. 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 pada ruang kerja.

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

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

Loop Tanpa Batas

Meskipun kode yang dihasilkan dijamin benar secara sintaksis setiap saat, kode ini mungkin berisi loop yang tidak terbatas. Karena penyelesaian masalah Penghentian berada di luar cakupan Blockly (!) pendekatan terbaik untuk menangani kasus ini adalah dengan 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 fungsi. Berikut 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 tentang cara membuat dan mengeksekusi JavaScript.

JS-Penerjemah

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

  • Jalankan kode dengan kecepatan apa pun.
  • Jeda/lanjutkan/langkah-langkah eksekusi.
  • Tandai blok saat dieksekusi.
  • Sepenuhnya terisolasi dari JavaScript browser.

Menjalankan Penerjemah

Pertama, download JS-Interpreter dari GitHub:

Download File ZIP Unduh TAR Ball Lihat di GitHub

Kemudian tambahkan ke halaman Anda:

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

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

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

Melangkahi Penerjemah

Untuk mengeksekusi kode lebih lambat, atau dengan cara yang lebih terkontrol, ganti panggilan ke run dengan loop yang berjalan (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, ini adalah unit semantik di JavaScript, yang mungkin sangat mendetail.

Menambahkan API

JS-Interpreter adalah sandbox yang sepenuhnya terisolasi dari browser. Setiap blok yang melakukan tindakan dengan dunia luar memerlukan API yang ditambahkan ke penafsir. Untuk deskripsi lengkap, lihat dokumentasi JS-Interpreter. Namun, sebagai permulaan, berikut API yang diperlukan untuk mendukung pemblokiran 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 Anda untuk meneruskan fungsi initApi:

var myInterpreter = new Interpreter(code, initApi);

Blok pemberitahuan dan perintah adalah satu-satunya dua 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 menyusuri program. Caranya, buat fungsi wrapper highlightBlock() guna merekam argumen fungsi, lalu mendaftarkannya 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 mengeksekusi langkah-langkah berulang kali tanpa jeda hingga perintah sorotan tercapai, lalu jeda. Strategi ini menyimulasikan eksekusi baris demi baris. Contoh di bawah ini menggunakan pendekatan ini.

Contoh JS-Penerjemah

Berikut adalah demo langsung cara menafsirkan JavaScript langkah demi langkah. Dan demo ini mencakup blok tunggu, contoh yang bagus untuk digunakan untuk perilaku asinkron lainnya (misalnya, ucapan atau audio, input pengguna).