Aplikasi blockly sering menghasilkan JavaScript sebagai bahasa {i>output<i} mereka, umumnya untuk dijalankan di 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 peningkatannya adalah eval digabungkan dalam
try
/catch
sehingga error runtime terlihat, bukan gagal
secara diam-diam. Perbaikan lainnya adalah code
ditambahkan ke daftar reservasi
kata sehingga jika kode pengguna berisi variabel dari nama itu,
berganti nama secara otomatis
dan tidak bertabrakan. Setiap variabel lokal harus
disediakan dengan cara ini.
Blok Sorotan
Menyoroti blok yang sedang dieksekusi saat kode berjalan membantu pengguna
memahami perilaku program mereka. Sorotan 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 menyebabkan pernyataan highlightBlock('123');
ditambahkan sebelum
setiap pernyataan, dengan 123
adalah nomor seri blok yang akan
ditandai.
Pengulangan Tanpa Batas
Meskipun kode yang dihasilkan dijamin benar secara sintaksis
berulang kali, parameter ini mungkin berisi
loop yang tidak terbatas. Sejak menyelesaikan
Menghentikan masalah melampaui batas
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 kode
yang akan dimasukkan ke dalam setiap loop dan setiap fungsi. Berikut adalah
contoh:
window.LoopTrap = 1000;
javascriptGenerator.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = javascriptGenerator.workspaceToCode(workspace);
Contoh
Berikut demo langsung pembuatan dan eksekusi JavaScript.
JS-Interpreter
Jika Anda serius menjalankan blok pengguna dengan benar, maka Project JS-Interpreter adalah jawabannya. Project ini terpisah dari Blockly, tetapi dibuat khusus untuk Blockly.
- Jalankan kode dengan kecepatan berapa pun.
- Menjeda/melanjutkan/melangkahi eksekusi.
- Tandai blok saat dieksekusi.
- Sepenuhnya terisolasi dari JavaScript browser.
Menjalankan Penerjemah
Pertama, download JS-Interpreter dari GitHub:
Kemudian tambahkan ke halaman Anda:
<script src="acorn_interpreter.js"></script>
Metode paling sederhana untuk memanggilnya adalah dengan membuat JavaScript, membuat penafsiran, 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 metode
panggil 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 bukan sebuah garis atau blok, itu adalah unit semantik dalam 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 penerjemahnya. Untuk deskripsi lengkap, lihat Dokumentasi JS-Interpreter. Namun untuk memulai, berikut adalah 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 untuk meneruskan fungsi initApi:
var myInterpreter = new Interpreter(code, initApi);
Blok pemberitahuan dan perintah adalah dua blok saja 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. Yang akan dilakukan
ini, buat fungsi wrapper highlightBlock()
untuk mengambil fungsi
default, dan 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 menjalankan langkah secara berulang tanpa berhenti sementara hingga mencapai perintah {i>highlight<i}, lalu berhenti. Strategi ini menyimulasikan eksekusi baris demi baris. Contoh di bawah menggunakan pendekatan ini.
Contoh JS-Interpreter
Berikut adalah demo langsung untuk menafsirkan JavaScript langkah demi langkah. Dan demo ini menyertakan blok tunggu, contoh yang baik untuk digunakan pada perilaku asinkron lainnya (misalnya, ucapan atau audio, input pengguna).