Các ứng dụng khối thường tạo JavaScript làm ngôn ngữ đầu ra, thường chạy trong một trang web (có thể giống như WebView hoặc WebView được nhúng). Giống như mọi trình tạo khác, bước đầu tiên là đưa trình tạo JavaScript vào.
import {javascriptGenerator} from 'blockly/javascript';
Để tạo JavaScript từ không gian làm việc, hãy gọi:
javascriptGenerator.addReservedWords('code');
var code = javascriptGenerator.workspaceToCode(workspace);
Mã kết quả có thể được thực thi ngay trong trang web đích:
try {
eval(code);
} catch (e) {
alert(e);
}
Về cơ bản, đoạn mã trên chỉ tạo mã và đánh giá mã đó. Tuy nhiên,
có một vài điểm tinh chỉnh. Một điểm tinh tế là eval được bao bọc trong
try
/catch
để hiển thị lỗi thời gian chạy thay vì không thành công
một cách thầm lặng. Một tinh chỉnh khác là code
được thêm vào danh sách đặt trước
để nếu mã của người dùng chứa biến có tên đó, thì mã sẽ
tự động đổi tên thay vì va chạm. Mọi biến cục bộ đều phải là
đặt trước theo cách này.
Khối đánh dấu
Việc làm nổi bật khối đang thực thi khi mã chạy sẽ giúp người dùng
hiểu hành vi của chương trình. Bạn có thể đánh dấu trên
từng tuyên bố bằng cách đặt STATEMENT_PREFIX
trước
cách tạo mã JavaScript:
javascriptGenerator.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
javascriptGenerator.addReservedWords('highlightBlock');
Định nghĩa highlightBlock
để đánh dấu khối trên không gian làm việc.
function highlightBlock(id) {
workspace.highlightBlock(id);
}
Điều này dẫn đến việc câu lệnh highlightBlock('123');
được thêm vào trước
mỗi câu lệnh, trong đó 123
là số sê-ri của khối
được làm nổi bật.
Vòng lặp vô hạn
Mặc dù mã kết quả được đảm bảo về cú pháp hoàn toàn chính xác
nên nó có thể chứa các vòng lặp vô hạn. Vì giải quyết
Vấn đề đang tạm dừng nằm ngoài phạm vi
Phạm vi của Blockly (!) Cách tốt nhất để xử lý những trường hợp này là
duy trì bộ đếm và giảm nó mỗi khi thực hiện lặp lại.
Để thực hiện việc này, chỉ cần đặt javascriptGenerator.INFINITE_LOOP_TRAP
thành một mã
đoạn mã này sẽ được chèn vào mỗi vòng lặp và mỗi hàm. Dưới đây là một
ví dụ:
window.LoopTrap = 1000;
javascriptGenerator.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = javascriptGenerator.workspaceToCode(workspace);
Ví dụ:
Sau đây là bản minh hoạ trực tiếp tạo và thực thi JavaScript.
Phiên dịch viên JS
Nếu bạn nghiêm túc về việc chạy các khối của người dùng đúng cách, thì Dự án Trình thông dịch JS là cách tiếp tục. Dự án này tách biệt với Blockly, nhưng được viết riêng cho Blockly.
- Thực thi mã với mọi tốc độ.
- Tạm dừng/tiếp tục/thực thi từng bước.
- Đánh dấu các khối khi chúng thực thi.
- Hoàn toàn tách biệt với JavaScript của trình duyệt.
Chạy Trình phiên dịch
Trước tiên, tải xuống Trình thông dịch JS từ GitHub:
Sau đó, thêm đoạn mã đó vào trang của bạn:
<script src="acorn_interpreter.js"></script>
Phương pháp đơn giản nhất để gọi lệnh này là tạo JavaScript, tạo phiên dịch và chạy mã:
var code = javascriptGenerator.workspaceToCode(workspace);
var myInterpreter = new Interpreter(code);
myInterpreter.run();
Bước trình thông dịch
Để thực thi mã chậm hơn hoặc theo cách được kiểm soát nhiều hơn, hãy thay thế
gọi đến run
bằng một vòng lặp mà bước (trong trường hợp này là một bước mỗi 10 mili giây):
function nextStep() {
if (myInterpreter.step()) {
setTimeout(nextStep, 10);
}
}
nextStep();
Lưu ý rằng mỗi bước không phải là một dòng hoặc một khối mà là một đơn vị ngữ nghĩa trong JavaScript, có thể cực kỳ chi tiết.
Thêm API
Trình thông dịch JS là một hộp cát hoàn toàn tách biệt với trình duyệt. Mọi khối thực hiện hành động với thế giới bên ngoài đều yêu cầu thêm API vào trình thông dịch. Để xem nội dung mô tả đầy đủ, hãy xem Tài liệu về Trình thông dịch JS. Nhưng để bắt đầu, dưới đây là API cần thiết để hỗ trợ khối cảnh báo và lời nhắc:
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));
}
Sau đó, hãy sửa đổi quá trình khởi chạy trình thông dịch để truyền vào hàm initApi:
var myInterpreter = new Interpreter(code, initApi);
Khối cảnh báo và nhắc nhở là 2 khối duy nhất trong bộ khối mặc định cần một API tuỳ chỉnh cho trình thông dịch.
Đang kết nối với highlightBlock()
Khi chạy trong Trình thông dịch JS, highlightBlock()
phải được thực thi
ngay lập tức, bên ngoài hộp cát, khi người dùng tham gia chương trình. Để làm điều này, hãy tạo một hàm trình bao bọc highlightBlock()
để ghi lại đối số hàm và đăng ký hàm đó làm hàm gốc.
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));
}
Các ứng dụng phức tạp hơn có thể muốn thực thi lặp lại các bước mà không tạm dừng cho đến khi đạt đến một lệnh làm nổi bật, sau đó tạm dừng. Chiến lược này mô phỏng việc thực thi từng dòng. Ví dụ bên dưới sử dụng phương pháp này.
Ví dụ về trình thông dịch JS
Sau đây là bản minh hoạ trực tiếp của chúng tôi về cách diễn giải JavaScript theo từng bước. Và bản minh hoạ này bao gồm một khối chờ, một ví dụ phù hợp để sử dụng cho các hành vi không đồng bộ khác (ví dụ: lời nói hoặc âm thanh, dữ liệu đầu vào của người dùng).