JavaScript generieren und ausführen

Blockanwendungen generieren oft JavaScript als Ausgabesprache, im Allgemeinen auf einer Webseite ausgeführt werden (möglicherweise dieselbe oder eine eingebettete WebView). Wie bei jedem Generator muss zuerst der JavaScript-Generator eingebunden werden.

import {javascriptGenerator} from 'blockly/javascript';

Um JavaScript-Code aus dem Arbeitsbereich zu generieren, rufen Sie Folgendes auf:

javascriptGenerator.addReservedWords('code');
var code = javascriptGenerator.workspaceToCode(workspace);

Der resultierende Code kann direkt auf der Zielwebseite ausgeführt werden:

try {
 
eval(code);
} catch (e) {
  alert
(e);
}

Im Grunde generiert das obige Snippet nur den Code und wertet ihn aus. Sie können jedoch gibt es einige Verfeinerungen. Eine Verfeinerung besteht darin, dass die Bewertung in try/catch, damit alle Laufzeitfehler sichtbar sind und nicht fehlschlagen leise. Außerdem wird code der Liste der reservierten Wörter hinzugefügt. Wenn der Code des Nutzers also eine Variable mit diesem Namen enthält, wird sie automatisch umbenannt, anstatt dass es zu einer Kollision kommt. Alle lokalen Variablen sollten die auf diese Weise reserviert sind.

Blöcke hervorheben

Wenn der aktuell ausgeführte Block während der Ausführung des Codes hervorgehoben wird, können Nutzer das Verhalten ihres Programms besser nachvollziehen. Die Markierung kann auf einem Anweisungsebene durch Festlegen von STATEMENT_PREFIX vor Generieren des JavaScript-Codes:

javascriptGenerator.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
javascriptGenerator
.addReservedWords('highlightBlock');

Definieren Sie highlightBlock, um den Block im Arbeitsbereich zu markieren.

function highlightBlock(id) {
  workspace
.highlightBlock(id);
}

Dies führt dazu, dass die Anweisung highlightBlock('123'); vor dem in jeder Anweisung, wobei 123 die Seriennummer des Blocks ist, der verwendet werden soll hervorgehoben.

Endlosschleifen

Auch wenn der resultierende Code garantiert syntaktisch korrekt ist kann er Endlosschleifen enthalten. Seit der Lösung des Das Anhalten des Problems Blocklys Aufgabenbereich (!) ist der beste Ansatz für den Umgang mit solchen Fällen, einen Zähler verwalten und bei jeder Durchführung dekrementiert werden. Legen Sie dazu einfach javascriptGenerator.INFINITE_LOOP_TRAP auf einen Code fest. Snippet, das in jede Schleife und Funktion eingefügt wird. Hier ein Beispiel:

window.LoopTrap = 1000;
javascriptGenerator
.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = javascriptGenerator.workspaceToCode(workspace);

Beispiel

Hier ist eine Live-Demo das Generieren und Ausführen von JavaScript.

JS-Interpreter

Wenn es Ihnen wichtig ist, die Nutzerblöcke korrekt auszuführen, JS-Interpreter-Projekt ist die richtige Wahl. Dieses Projekt ist unabhängig von Blockly, wurde aber speziell für Blockly geschrieben.

  • Sie können Code mit jeder Geschwindigkeit ausführen.
  • Ausführung pausieren/fortsetzen/schrittweise ausführen.
  • Blöcke beim Ausführen hervorheben
  • Vollständig vom JavaScript des Browsers isoliert.

Dolmetscher ausführen

Laden Sie zuerst den JS-Interpreter von GitHub herunter:

ZIP-Datei herunterladen TAR Ball herunterladen Auf GitHub ansehen

Fügen Sie es dann zu Ihrer Seite hinzu:

<script src="acorn_interpreter.js"></script>

Die einfachste Methode zum Aufrufen besteht darin, das JavaScript zu generieren, den Interpreter zu erstellen und den Code auszuführen:

var code = javascriptGenerator.workspaceToCode(workspace);
var myInterpreter = new Interpreter(code);
myInterpreter
.run();

Schritt für Schritt Dolmetscher

Um den Code langsamer oder kontrollierter auszuführen, ersetzen Sie den Parameter Aufruf von run mit einer Schleife (in diesem Fall ein Schritt alle 10 ms):

function nextStep() {
 
if (myInterpreter.step()) {
    setTimeout
(nextStep, 10);
 
}
}
nextStep
();

Jeder Schritt ist keine Linie oder Block, sondern eine semantische Einheit in JavaScript-Code, der sehr detailliert sein kann.

API hinzufügen

Der JS-Interpreter ist eine Sandbox, die vollständig vom Browser isoliert ist. Für alle Blöcke, die Aktionen mit der Außenwelt durchführen, ist eine API erforderlich, die für den Dolmetscher. Eine vollständige Beschreibung finden Sie in der JS-Interpreter-Dokumentation Hier ist jedoch zuerst die API, die zur Unterstützung der Blockierungen für Warnungen und Aufforderungen erforderlich ist:

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));
}

Ändern Sie dann die Interpreter-Initialisierung, um die initApi-Funktion zu übergeben:

var myInterpreter = new Interpreter(code, initApi);

Die Blockierungen mit Benachrichtigungen und Aufforderungen sind die einzigen beiden Blockierungen in der Standardreihe. die eine benutzerdefinierte API für den Interpreter erfordern.

Verknüpfung mit highlightBlock() wird hergestellt

Bei Ausführung im JS-Interpreter sollte highlightBlock() ausgeführt werden. direkt außerhalb der Sandbox, während der Nutzer das Programm durchläuft. Aufgabe Erstellen Sie die Wrapper-Funktion highlightBlock(), um die Funktion -Argument und registrieren Sie es als native Funktion.

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));
}

Komplexere Anwendungen möchten möglicherweise wiederholt Schritte ausführen, halten Sie an, bis ein Hervorhebungsbefehl erreicht ist, und halten Sie dann an. Diese Strategie simuliert die zeilenweise Ausführung. Im folgenden Beispiel wird dieser Ansatz verwendet.

JS-Interpreter-Beispiel

Hier ist eine Live-Demo der Interpretation von JavaScript. Und dieser Demo enthält einen Warteblock, ein gutes Beispiel für ein anderes asynchrones Verhalten (z.B. Sprache oder Audio, Nutzereingabe).