Aplikacje Blockly często generują JavaScript jako język wyjściowy, zwykle działa na stronie internetowej (prawdopodobnie w tym samym lub w umieszczonym komponencie WebView). Tak jak w przypadku każdego generatora, pierwszym krokiem jest dołączenie generatora JavaScript.
import {javascriptGenerator} from 'blockly/javascript';
Aby wygenerować kod JavaScript z obszaru roboczego, wywołaj:
javascriptGenerator.addReservedWords('code');
var code = javascriptGenerator.workspaceToCode(workspace);
Uzyskany kod można wykonać bezpośrednio na stronie docelowej:
try {
eval(code);
} catch (e) {
alert(e);
}
Zasadniczo ten fragment kodu tylko generuje i ocenia. Pamiętaj jednak:
wprowadziliśmy kilka
doprecyzowań. Jedną z doprecyzowań jest to, że ocena jest objęta funkcją
try
/catch
, aby były widoczne wszystkie błędy działania, a nie
cicho. Kolejnym ulepszeniem jest dodanie słowa code
do listy słów zarezerwowanych, dzięki czemu, jeśli kod użytkownika zawiera zmienną o tej nazwie, zostanie ona automatycznie przemianowana zamiast powodować konflikt. Wszystkie zmienne lokalne powinny być
w ten sposób.
Bloki z najciekawszymi momentami
Wyróżnianie aktualnie uruchomionego bloku podczas uruchamiania kodu pomaga użytkownikom
zrozumieć zachowanie w programie. Wyróżnianie można umieścić na
poziomu instrukcji, ustawiając STATEMENT_PREFIX
przed
generując kod JavaScript:
javascriptGenerator.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
javascriptGenerator.addReservedWords('highlightBlock');
Określ highlightBlock
, aby oznaczyć bryłę w obszarze roboczym.
function highlightBlock(id) {
workspace.highlightBlock(id);
}
W efekcie przed każdą instrukcją zostanie dodana instrukcja highlightBlock('123');
, gdzie 123
to numer seryjny bloku, który ma zostać wyróżniony.
Nieskończone pętle
Mimo że wygenerowany kod będzie w ogóle poprawny pod względem składni
może zawierać nieskończone pętle. Od momentu rozwiązania
Problem z blokowaniem jest poza zakresem
W zakresie Blockly (!) najlepszym podejściem do takich przypadków jest
utrzymuje licznik i zmniejsza go przy każdym wykonaniu iteracji.
Aby to zrobić, ustaw javascriptGenerator.INFINITE_LOOP_TRAP
jako kod
który zostanie wstawiony do każdej pętli i każdej funkcji. Oto przykład:
window.LoopTrap = 1000;
javascriptGenerator.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = javascriptGenerator.workspaceToCode(workspace);
Przykład
Oto demo na żywo generowania i wykonywania kodu JavaScript.
Tłumacz języka JS
Jeśli poważnie podchodzisz do poprawnego uruchamiania blokad użytkownika, Projekt JS-Interpreter to słuszny wybór. Ten projekt jest czymś innym niż Blockly, ale został napisany z myślą o Blockly.
- Uruchamiaj kod z dowolną szybkością.
- Wstrzymaj/wznów/krok po kroku.
- Zaznaczaj wykonywane bloki.
- Jest całkowicie odizolowany od JavaScriptu w przeglądarce.
Uruchamianie tłumaczenia rozmowy
Najpierw pobierz JS-Interpreter z GitHuba:
Następnie dodaj go do swojej strony:
<script src="acorn_interpreter.js"></script>
Najprostszą metodą jego wywołania jest wygenerowanie JavaScriptu, utworzenie interpreter i uruchom kod:
var code = javascriptGenerator.workspaceToCode(workspace);
var myInterpreter = new Interpreter(code);
myInterpreter.run();
Postaw na tłumacza
Aby wykonywać kod wolniej lub w sposób bardziej kontrolowany, zastąp
wywołaj run
z pętlą wykonującą kroki (w tym przypadku co 10 ms):
function nextStep() {
if (myInterpreter.step()) {
setTimeout(nextStep, 10);
}
}
nextStep();
Pamiętaj, że każdy krok nie jest linią ani blokiem, jest jednostką semantyczną w JavaScript, który może być bardzo szczegółowy.
Dodaj interfejs API
Tłumacz JS to piaskownica, która jest całkowicie odizolowana od przeglądarki. Wszystkie bloki wykonujące działania w świecie zewnętrznym wymagają dodania interfejsu API tłumaczem. Pełny opis znajdziesz tutaj Dokumentacja JS-Interpreter Na początek przedstawiamy interfejs API potrzebny do obsługi bloków alertów i promptów:
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));
}
Następnie zmodyfikuj inicjowanie interpretera tak, by przekazywać do funkcji initApi:
var myInterpreter = new Interpreter(code, initApi);
Bloki alertów i promptów to jedyne 2 bloki w domyślnym zestawie bloków które wymagają niestandardowego interfejsu API dla tłumaczenia rozmowy.
Łączę z dostawcą highlightBlock()
W przypadku użycia interpretera JS należy wykonać polecenie highlightBlock()
natychmiast, poza piaskownicą, w miarę jak użytkownik przechodzi przez program. Do zrobienia
utwórz funkcję opakowań highlightBlock()
, aby przechwycić funkcję
i zarejestruj go jako funkcję natywną.
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));
}
Bardziej zaawansowane aplikacje mogą wielokrotnie wykonywać czynności bez wstrzymywania, aż do momentu, gdy dojdzie do polecenia wyróżnienia, a następnie wstrzymania. Ta strategia symuluje wykonanie linii po linii. Tę metodę zastosowano w przykładzie poniżej.
Przykład tłumaczenia rozmowy JS
Oto demo na żywo, które krok po kroku pokazuje interpretację kodu JavaScript. oraz ta wersja demonstracyjna zawiera blok oczekiwania, co jest dobrym przykładem do innych działań asynchronicznych. (np. mowa lub dźwięk, dane wejściowe użytkownika).