แอปพลิเคชัน Blockly มักจะสร้าง JavaScript เป็นภาษาเอาต์พุต ซึ่งโดยทั่วไปจะทํางานภายในหน้าเว็บ (อาจเป็นหน้าเว็บเดียวกันหรือ WebView ที่ฝังอยู่) ขั้นตอนแรกคือรวมโปรแกรมสร้าง JavaScript เช่นเดียวกับโปรแกรมสร้างอื่นๆ
import {javascriptGenerator} from 'blockly/javascript';
หากต้องการสร้าง JavaScript จากพื้นที่ทำงาน ให้เรียกใช้
javascriptGenerator.addReservedWords('code');
var code = javascriptGenerator.workspaceToCode(workspace);
โค้ดที่ได้จะเรียกใช้ได้ทันทีในหน้าเว็บปลายทาง ดังนี้
try {
eval(code);
} catch (e) {
alert(e);
}
โดยพื้นฐานแล้ว ข้อมูลโค้ดด้านบนจะสร้างโค้ดและประเมิน อย่างไรก็ตาม
มีการปรับแต่ง 2 แบบ การปรับเกณฑ์การค้นหาอย่างหนึ่งคือ eval จะถูกรวมไว้ใน
try
/catch
เพื่อให้มองเห็นข้อผิดพลาดรันไทม์ได้ แทนที่จะล้มเหลว
เงียบๆ การปรับเกณฑ์การค้นหาอีกรายการคือ code
ถูกเพิ่มในรายการของรายการที่สงวนไว้
ดังนั้นถ้าโค้ดของผู้ใช้มีตัวแปรของชื่อ
จะเปลี่ยนชื่อใหม่โดยอัตโนมัติแทนที่จะซ้อนทับกัน คุณควรสงวนตัวแปรในเครื่องด้วยวิธีนี้
บล็อกไฮไลต์
การไฮไลต์บล็อกที่กำลังเรียกใช้เนื่องจากโค้ดเรียกใช้จะช่วยให้ผู้ใช้
เข้าใจพฤติกรรมโปรแกรมของตน การไฮไลต์อาจทำได้ใน
ระดับคำชี้แจงต่อข้อความโดยการตั้งค่า STATEMENT_PREFIX
ก่อนวันที่
การสร้างโค้ด JavaScript:
javascriptGenerator.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
javascriptGenerator.addReservedWords('highlightBlock');
กําหนด highlightBlock
เพื่อทําเครื่องหมายการบล็อกในพื้นที่ทำงาน
function highlightBlock(id) {
workspace.highlightBlock(id);
}
สิ่งนี้ส่งผลให้มีการเพิ่มใบแจ้งยอด highlightBlock('123');
ไปยังก่อนหน้า
ทุกคำสั่ง โดยที่ 123
คือหมายเลขซีเรียลของบล็อก
ไฮไลต์ไว้
วนซ้ำไม่สิ้นสุด
แม้ว่าโค้ดที่ได้จะรับประกันความถูกต้องทางไวยากรณ์เลย
อาจมีการวนรอบไปเรื่อยๆ ได้ไม่รู้จบ ตั้งแต่การแก้โจทย์
การแก้ไขปัญหานั้นไม่ใช่แค่
ขอบเขต (!) ของ Blockly วิธีที่ดีที่สุดในการจัดการกับกรณีเหล่านี้คือ
รักษาตัวนับและลดจำนวนโฆษณาทุกครั้งที่มีการทำซ้ำ
หากต้องการดำเนินการดังกล่าว เพียงตั้งค่า javascriptGenerator.INFINITE_LOOP_TRAP
เป็นโค้ด
ซึ่งจะแทรกลงในทุกลูปและทุกฟังก์ชัน นี่คือ
ตัวอย่าง:
window.LoopTrap = 1000;
javascriptGenerator.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = javascriptGenerator.workspaceToCode(workspace);
ตัวอย่าง
ต่อไปนี้คือการสาธิตแบบเรียลไทม์ในการสร้างและเรียกใช้ JavaScript
ล่าม JS
หากคุณจริงจังกับการเรียกใช้การบล็อกของผู้ใช้อย่างถูกต้อง นี่คือโปรเจ็กต์ JS-Interpreter ของเรา โปรเจ็กต์นี้แยกต่างหากจาก Blockly แต่เขียนขึ้นเพื่อ Blockly โดยเฉพาะ
- เรียกใช้โค้ดด้วยความเร็วใดก็ได้
- หยุดชั่วคราว/กลับมาทำงานอีกครั้ง/การดำเนินการแบบทีละขั้นตอน
- ไฮไลต์บล็อกขณะที่ดำเนินการ
- แยกออกจาก JavaScript ของเบราว์เซอร์โดยสมบูรณ์
เรียกใช้ล่าม
ก่อนอื่น ให้ดาวน์โหลด JS-Interpreter จาก GitHub ดังนี้
จากนั้นเพิ่มลงในหน้าเว็บโดยทำดังนี้
<script src="acorn_interpreter.js"></script>
วิธีที่ง่ายที่สุดในการเรียกใช้คือการสร้าง JavaScript, สร้างโปรแกรมตีความ และเรียกใช้โค้ด
var code = javascriptGenerator.workspaceToCode(workspace);
var myInterpreter = new Interpreter(code);
myInterpreter.run();
ก้าวเข้าสู่ล่าม
หากต้องการเรียกใช้โค้ดให้ช้าลงหรือในลักษณะที่ควบคุมได้มากขึ้น ให้แทนที่
โทรหา run
พร้อมวนซ้ำขั้นตอน (ในกรณีนี้ 1 ขั้นตอนทุกๆ 10 มิลลิวินาที):
function nextStep() {
if (myInterpreter.step()) {
setTimeout(nextStep, 10);
}
}
nextStep();
โปรดทราบว่าแต่ละขั้นตอนไม่ใช่บรรทัดหรือบล็อก แต่เป็นหน่วยเชิงความหมายใน JavaScript ซึ่งอาจมีความซับซ้อนมาก
เพิ่ม API
JS-Interpreter คือแซนด์บ็อกซ์ที่แยกจากเบราว์เซอร์โดยสมบูรณ์ บล็อกที่ดำเนินการกับโลกภายนอกจะต้องเพิ่ม API ลงในโปรแกรมแปล สำหรับคำอธิบายทั้งหมด โปรดดูที่ เอกสารประกอบสำหรับโหมดล่ามของ JS แต่หากต้องการเริ่มต้น ต่อไปนี้เป็น API ที่จำเป็นสำหรับการรองรับการบล็อกการแจ้งเตือนและข้อความแจ้ง
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));
}
จากนั้นแก้ไขการเริ่มต้นล่ามให้ส่งผ่านในฟังก์ชัน initApi ดังนี้
var myInterpreter = new Interpreter(code, initApi);
การบล็อกการแจ้งเตือนและข้อความแจ้งเป็นการบล็อกเพียง 2 รายการในชุดการบล็อกเริ่มต้น ที่ต้องใช้ API ที่กำหนดเองสำหรับล่าม
กำลังเชื่อมต่อกับ highlightBlock()
ควรเรียกใช้ highlightBlock()
เมื่อเรียกใช้ใน JS-Interpreter
ทันทีนอกแซนด์บ็อกซ์ ขณะที่ผู้ใช้เดินผ่านโปรแกรม สิ่งต้องทำ
สร้างฟังก์ชัน Wrapper highlightBlock()
เพื่อบันทึกฟังก์ชัน
และลงทะเบียนเป็นฟังก์ชันเนทีฟ
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));
}
แอปพลิเคชันที่ซับซ้อนมากขึ้นอาจต้องการดำเนินการตามขั้นตอนต่างๆ ซ้ำๆ โดยไม่มี หยุดชั่วคราวจนกว่าจะถึงคำสั่งไฮไลต์ แล้วหยุดชั่วคราว กลยุทธ์นี้จำลอง แบบทีละบรรทัด ตัวอย่างด้านล่างใช้วิธีนี้
ตัวอย่าง JS-ล่าม
ต่อไปนี้คือการสาธิตแบบเรียลไทม์ของการตีความ JavaScript แบบทีละขั้นตอน และ การสาธิตนี้ มีช่วงรอ ซึ่งเป็นตัวอย่างที่ดีที่จะใช้สำหรับลักษณะการทำงานอื่นๆ ที่ไม่พร้อมกัน (เช่น คำพูดหรือเสียง ข้อมูลจากผู้ใช้)