Lässt es sich mit cremefarbenem Papier, einer Tönung, mehr Kontrast oder größerer Schrift besser lesen? Wählen Sie Ihre Farben und Ihre Schrift, einmalig für alle Seiten.

Kostenlose Lektion

Async, await und Datenstrom

Nach dieser Lektion: Ich kann sagen, warum ein langsamer Aufruf abgewartet wird und wie eine Antwort im Datenstrom ankommt.

Lektion, 60 Min.3 BefehleLab für KI-Coding-Agenten: mit opencode Code erklären und reparieren lassen und die Arbeit prüfen

Ein langsamer Aufruf darf nichts einfrieren

Ein Aufruf an ein Modell kann mehrere Sekunden dauern. Ihr Programm soll beim Warten nicht einfrieren. Asynchroner Code lässt es warten, ohne zu blockieren.

Der Datenstrom geht noch einen Schritt weiter. Die Antwort kommt in Stücken an, und man kann sofort zu lesen beginnen.

Am Ende dieser Lektion

Notiz

Ich kann sagen, warum ein langsamer Aufruf abgewartet wird und wie eine Antwort im Datenstrom ankommt.

Schlüsselwörter

BegriffWas er bedeutet
Promiseein Platzhalter für ein Ergebnis, das noch nicht da ist
Awaiteine Funktion anhalten, bis eine Promise ihr Ergebnis hat
Async-Funktioneine Funktion, die await benutzen darf
Datenstromeine Antwort, die in Stücken gesendet wird, während sie entsteht
Teilstückein Stück einer Antwort im Datenstrom

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Ein langsamer Aufruf liefert eine Promise

Starten Sie eine langsame Arbeit, kehrt der Aufruf sofort mit einer Promise zurück. Das Ergebnis ist noch nicht da. Ihr Programm macht mit der nächsten Zeile weiter.

Kommt das Ergebnis, liefert es die Promise. Die Reihenfolge zählt: Zeilen nach dem Aufruf können vor dem Ergebnis laufen.

Die Reihenfolge der Ereignisse sehen

Befehl
docker exec -w /home/node/project agent node -e "const warten=(ms,t)=>new Promise(r=>setTimeout(()=>r(t),ms));console.log('1 Start');warten(300,'3 der langsame Aufruf ist fertig').then(console.log);console.log('2 das Programm läuft weiter')"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Await hält eine Funktion an, nicht das Programm

In einer Async-Funktion hält await diese Funktion an, bis die Promise ihr Ergebnis hat. Der Rest des Programms wird nicht blockiert.

Zwei langsame Aufrufe, die nicht voneinander abhängen, können mit Promise.all zusammen starten. Das dauert ungefähr so lange wie der langsamere, nicht beide zusammen.

Erst nacheinander, dann gleichzeitig abwarten

Befehl
docker exec -w /home/node/project agent node -e "const warten=(ms,t)=>new Promise(r=>setTimeout(()=>r(t),ms));const runden=(t0)=>Math.round((Date.now()-t0)/100)*100;(async()=>{let t0=Date.now();await warten(200,'a');await warten(200,'b');console.log('nacheinander: etwa '+runden(t0)+' ms');t0=Date.now();await Promise.all([warten(200,'a'),warten(200,'b')]);console.log('gleichzeitig: etwa '+runden(t0)+' ms')})()"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Eine Antwort im Datenstrom kommt in Teilstücken

Fordern Sie stream: true an, sendet der Dienst die Antwort, während er sie erzeugt. Die meisten Modell-APIs nutzen Server-Sent Events: Zeilen, die mit data: beginnen und je ein kleines Stück Text tragen.

Die letzte Zeile ist data: [DONE]. Fügen Sie die Stücke der Reihe nach zusammen, um die ganze Antwort zu erhalten.

Beispiel: ein Datenstrom, Zeile für Zeile

Empfangene ZeileWas sie ergibt
data: {"choices":[{"delta":{"content":"Hal"}}]}Hal
data: {"choices":[{"delta":{"content":"lo"}}]}lo
data: [DONE]Das Ende, ohne Text
ZusammengefügtHallo

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Eine Antwort im Datenstrom lesen

Befehl
docker exec -w /home/node/project agent node -e "const u=(process.env.AI_URL||'http://ai:4000')+'/v1/chat/completions';(async()=>{try{const r=await fetch(u,{method:'POST',headers:{'content-type':'application/json',authorization:'Bearer lab'},body:JSON.stringify({model:'lab',messages:[{role:'user',content:'Zählen Sie von eins bis fünf.'}],max_tokens:40,stream:true})});if(r.ok===false)throw new Error(r.status);const d=new TextDecoder();let b='',n=0,t='';for await(const p of r.body){b+=d.decode(p,{stream:true});const z=b.split(String.fromCharCode(10));b=z.pop();for(const l of z){const x=l.slice(6);if(l.startsWith('data: ')&&(x==='[DONE]')===false){const c=JSON.parse(x).choices?.[0]?.delta?.content;if(c){n++;t+=c}}}}console.log('Teilstücke mit Text: '+n);console.log('Zusammengesetzter Text: '+t)}catch(e){console.log('Kein Strom ('+e.message+'). Aufgezeichnetes Beispiel:');console.log('Teilstücke mit Text: 5');console.log('Zusammengesetzter Text: eins, zwei, drei, vier, fünf')}})()"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Ein häufiger Fehler

Warnung

Viele glauben, ein Datenstrom mache das Modell schneller. Die ganze Antwort dauert ungefähr gleich lang. Sie sehen die ersten Wörter früher, und das fühlt sich schneller an. Ein Strom kann auch mittendrin abbrechen: Prüfen Sie, ob die Endmarke angekommen ist.

Über dieses Lab und seinen Quellcode: Lab für KI-Coding-Agenten: mit opencode Code erklären und reparieren lassen und die Arbeit prüfen

Sie unterrichten eine Gruppe? Weisen Sie dieses Modul Ihren Studierenden zu, mit Handbuch für Lehrende, automatisch geprüften Aufgaben und einem Lab für jede Person.