แอปพลิเคชัน 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);
}
โดยพื้นฐานแล้ว ข้อมูลโค้ดข้างต้นจะสร้างโค้ดและประเมินโค้ดนั้น อย่างไรก็ตาม
มีการปรับแต่งเล็กน้อย การปรับแต่งอย่างหนึ่งคือการห่อหุ้ม 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
คือหมายเลขซีเรียลของบล็อกที่จะ
ไฮไลต์
Infinite Loops
แม้ว่าโค้ดที่ได้จะรับประกันว่าถูกต้องตามไวยากรณ์ตลอดเวลา แต่ก็อาจมีลูปที่ไม่มีที่สิ้นสุด เนื่องจากการแก้ปัญหาการหยุดทำงานอยู่นอกเหนือขอบเขตของ 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-Interpreter
หากคุณต้องการให้การบล็อกของผู้ใช้ทำงานอย่างถูกต้อง โปรเจ็กต์ 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();
Step the Interpreter
หากต้องการเรียกใช้โค้ดให้ช้าลงหรือในลักษณะที่มีการควบคุมมากขึ้น ให้แทนที่การเรียกใช้ run
ด้วยลูปที่ก้าว (ในกรณีนี้คือ 1 ก้าวทุกๆ 10 มิลลิวินาที) ดังนี้
function nextStep() {
if (myInterpreter.step()) {
setTimeout(nextStep, 10);
}
}
nextStep();
โปรดทราบว่าแต่ละขั้นตอนไม่ใช่บรรทัดหรือบล็อก แต่เป็นหน่วยเชิงความหมายใน JavaScript ซึ่งอาจมีความละเอียดสูงมาก
เพิ่ม API
JS-Interpreter เป็นแซนด์บ็อกซ์ที่แยกจากเบราว์เซอร์โดยสมบูรณ์ บล็อกที่ดำเนินการกับโลกภายนอกต้องมี API เพิ่มใน อินเทอร์พรีเตอร์ ดูคำอธิบายทั้งหมดได้ในเอกสารประกอบของ JS-Interpreter แต่ก่อนอื่น คุณต้องมี 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()
เมื่อเรียกใช้ใน JS-Interpreter highlightBlock()
ควรดำเนินการ
ทันทีนอกแซนด์บ็อกซ์ ขณะที่ผู้ใช้ทำตามขั้นตอนในโปรแกรม หากต้องการทำเช่นนี้ ให้สร้างฟังก์ชัน 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-Interpreter
ดูการสาธิตสด การตีความ JavaScript แบบทีละขั้นตอนได้ที่นี่ และการสาธิต นี้มีบล็อกรอ ซึ่งเป็นตัวอย่างที่ดีในการใช้กับลักษณะการทำงานแบบอะซิงโครนัสอื่นๆ (เช่น คำพูดหรือเสียง ข้อมูลที่ผู้ใช้ป้อน)