Rolf B: Coding Roboter alle Schritte voneinander trennen

Beitrag lesen

Hallo Samuel,

das Problem ist, dass eine async-Funktion mit einem Promise zurückkehrt, sobald der Code auf einen await stößt. Code, der erst laufen soll, wenn alle asnychronen Teile der Funktion ausgeführt sind, muss im then-Teil dieses Promise laufen.

async/await kapseln Promises lediglich. D.h. wenn ich dies tue:

nachVorne();
nachVorne();
nachVorne();

dann kehrt der erste Aufruf fast sofort zurück und sein Delay läuft im Hintergrund ab. D.h. der zweite Aufruf erfolgt fast sofort nach dem ersten, der dritte gleich hinterher. Die setTimeout-Verzögerungen aller Aufrufe überlappen sich zum größten Teil, und dann rendern sie wieder direkt nacheinander.

Wenn Du willst, dass ein nachVorne Aufruf auf den vorigen wartet, muss das mit Promises so aussehen:

nachVorne()
.then(() => nachVorne())
.then(() => nachVorne());

Await ist Syntaxzucker dafür, dies hier tut im Wesentlichen das Gleiche:

await nachVorne();
await nachVorne();
nachVorne();

Das fliegt Dir aber um die Ohren, weil await nur in einer async-Funktion erlaubt ist. Ein eval-Kontext ist keine async-Funktion. Du müsstest im Code-Feld beispielsweise schreiben:

async function run() 
{
await nachVorne();
await nachVorne();
await nachVorne();
await nachVorne();
}

run();

Dann geht es, weil er nun nach jedem Schritt wirklich wartet.

Man kann es auch mit einer Immediately Invoked Function Expression (IIFE) machen:

(async function() {
  await nachVorne();
  await nachVorne();
  await nachVorne();
  await nachVorne();
})()

und jetzt wird's interessanter, denn die awaits kann man durch search&replace in den Textarea-Inhalt hineinzaubern und die beiden Zeilen, die den IIFE-Rahmen bilden, noch drumherumbauen.

Deine start-Funktion könnte so aussehen:

function start() {
  let text = document.getElementById('code')
                     .value
                     .replace(/nachVorne|dreheLinks|dreheRechts/g,
                              m => "await " + m);
  eval("(async function() {" + text + "})()");
}

Und damit kannst Du in dein Codefeld auch dies schreiben:

for (i=0; i<10; i++) {
 nachVorne();
 dreheLinks();
}

Das wird automatisch konvertiert zu

(async function() {for (i=0; i<10; i++) {
 await nachVorne();
 await dreheLinks();
}})()

und schön schrittweise ausgeführt.

Lediglich die Drehung des Kopfes von 270 auf 0 ist noch ätzend. Er dreht nicht um 90°, sondern um 270° in die Gegenrichtung. Viel Spaß damit.

Rolf

--
sumpsi - posui - obstruxi