JavaScript async await, nicht parallel?

Hendoul

Commander
Registriert
Apr. 2008
Beiträge
2.049
Hi :)

Ich bin grad dabei mir die Thematik mit Promise und nun auch async await anzuschauen.

Warum laufen hier mit Promise die calls parallel? Es dauert maximal 10s bis alle durch sind.
https://jsfiddle.net/GarfieldKlon/9d1xLr27/

Und mit async await nicht? Hier wird immer gewartet, bis das eine Promise komplett durchlief.
https://jsfiddle.net/GarfieldKlon/1o708gf3/


Kurze Erklärung zum Code:
Es werden 10 promises erstellt die jeweils zeitverzögert ausgeführt werden. Falls eine generierte Zufallszahl > 5 ist, wird das Promise resolved, ansonsten rejected.


Sprich wenn man async/await benutzt wird bei await angehalten und erst im code fortgefahren, sobald das Promise resolved/rejected wurde? Oder was mache ich falsch?

Ich dachte async/await sei Syntax-Sugar, und nicht, dass sich die Funktionalität ändert. Aber ich glaube ich habe irgendwas übersehen bei dem Konzept...
 
Mit dem Starten einer async Funktion startest du die Funktion, dein Code steigt also dorthin ab. Irgendwann kehrt die Ausführung aber wieder in die äußere Funktion zurück. Das besondere ist hier, dass die Async-Funktion noch gar nicht fertig sein muss, eventuell bloß auf das Freiwerden anderer Ressourcen wartet. Dein Programm kann solange weiterlaufen, bis du das await aufrufst - dann wartet das Programm, bis die async-Funktion tatsächlich ein Ergebnis hast. Wann die async-Funktion wieder zurückkehrt und deine Ausführung bis zum await erlaubt, hängt von der Funktion ab.

async-await implementiert kein echtes Multitasking, damit kannst du nur Wartevorgänge auf Ressourcen sinnvoll nutzen. Die Aufrufe werden trotzdem noch sequentiell abgearbeitet.
 
  • Gefällt mir
Reaktionen: psYcho-edgE
Ja aber wenn z.B. eine Async Methode 10s braucht um etwas zu erledigen, dann kann ich nicht einfach diese Zeit mit etwas sinnvollem auffüllen ;)

Die Async function ruft man doch meistens so direkt auf? let xyz = await myAsyncFunction();
Oder wie hast du dein Beispiel gemeint?


Mit Promises.all kann man anscheinend dann auch mehrere Tasks parallel laufen lassen. Mit gewissem Risiko halt, dass einer failed.

https://stackoverflow.com/questions...t-in-parallel-in-javascript/42158854#42158854
 
Hendoul schrieb:
Ja aber wenn z.B. eine Async Methode 10s braucht um etwas zu erledigen, dann kann ich nicht einfach diese Zeit mit etwas sinnvollem auffüllen
Wenn sie dabei die Loop blockiert, ist das die falsche Anwendung von Promise/async/await. Und wenn man 10s lang die Loop blockiert, macht man meistens (nicht immer) etwas falsch.
 
Der Sinn von async&await ist es eine bessere Syntax für promise chains (.then()) zu haben, da die halt absurd widerlich sind, genau wie promises die Lösung für die callback hell sind. Deine Beispiele machen halt 2 grundlegend verschiedene Dinge. Das eine wartet nur aufs promise um dann console.log zu machen (mit .then()), das andere wartet aufs promise um weiterzumachen.

Wenn du auf mehrere parallel warten willst, dann machst du das wie in einer promise chain, nur statt .then() benutzt du halt await, also:
Javascript:
await Promise.all([promise1(), promise1()]);

Oder in anderen Worten: Statt then().then().then() kannst du async&await nutzen. In deinem Beispiel willst du aber gar nicht warten, sondern nur console.log machen, da macht await keinen Sinn.

Edit: Um die gleiche Funktionalität mit await zu erhalten könntest du z.B. das machen:
Javascript:
function setup() {
    for (i=1; i<=10; i++) {
        (async function(){
            try {
                let promise = await promiseTRRARNOSG(i);
                console.log("success " + promise.counter + " " + promise.randomNumberOfSeconds + " " +         promise.randomiseResolving);
            } catch(error){
                console.error("error " + error.counter  + " " + error.randomNumberOfSeconds + " " +     error.randomiseResolving);
            }
        })();
  }
}
Aber wie gesasgt, macht hier einfach keinen Sinn, da eh nur ein .then() nötig ist.
 
Zuletzt bearbeitet:
Direkt ein await auf eine Funktion feuern führt auch das await ad absurdum. Man arbeitet mit den Promises, sonst gibt es keinen Mehrwert.

Um mal aus coolmodis Beispiel zu nehmen:
Javascript:
let promise = promiseTRRARNOSG(i);
// irgendwas anderes, was das Ergebnis nicht braucht, während unsere funktion nebenläufig auf irgendwas wartet
let result = await promise;
 
  • Gefällt mir
Reaktionen: abcddcba
Doch, natürlich ergibt das Sinn. Bspw. wenn du ein Datenbank aufruf machst und darauf warten musst, bevor du das über http zurück gibst. Wohl 95% meiner awaits stehen direkt vor dem Funktionsaufruf.
 
  • Gefällt mir
Reaktionen: pcBauer
Wenn deine Datenbank 10 Sekunden für ein SELECT FROM dbo.irgendwas braucht würde ich eine andere Datenbank fragen, ob sie mit mir geht :)
 
Du zeigst nur, dass du keine Ahnung hast.
Auch wenn die Datenbank 0.1s braucht, ist dieser Vorgang asynchron. Früher hätte man das mit schönen Callbacks geregelt, dann mit Promises, und heute eben mit async/await.

Javascript:
function load(id, callback) {
    database.find({ id: id }, function (error, result) {
        if (error) {
            callback(error, null);
        } else {
            callback(null, result);
        }
    });
}

load(68732, function (error, result) {
    if (error != null) {
        console.error(error);
    } else {
        console.log(result);
    }
});

vs.

Javascript:
async function load(id) {
    return await database.find({ id: id });
}

try {
    const result = await load(68732);
    console.log(result);
} catch(error) {
    console.error(error);
}

Und hier haben wir nur eine einzige asynchrone aufgabe. Bei mehr würden die die meisten bei callbacks in die callback-hell fallen, bei async/await kommt einfach ein weiteres await func() dazu, in das selbe try catch, statt jedes mal ein weitere Prüfung auf error zu benötigen. Und wenn load noch irgendwas aufrufen sollte, wird der error einfach im Stack durchgereicht, statt auch da weitere ifs hinzuzufügen.

Das heit rein gar nichts mit der Dauer zu tun.
 
Zuletzt bearbeitet:
Ok, ich sehe jetzt, dass async/await dafür gedacht ist, nicht immer .then().then().then()... schreiben zu müssen.
Und zwischen dem Aufruf der etwas zeitintensives macht und dem await kann man noch weitere Dinge machen (was auch immer, mir fällt immer noch nichts gescheites dazu ein).

Z.B. könnte man in der Zwischenezeit auf 1'000'000'000 zählen und das await würde brav warten und danach das result der async function ausspucken.


Code:
async function blub() {
    return new Promise( (resolve, reject) => {
  setTimeout( () => {
        resolve("huba");
      }, 3 * 1000);
  });
}

async function test() {
    console.log('start test');
  for(var i = 1; i <= 1000000000; i++) {
      if(i % 100000000 == 0 ){
        console.log(i/100000000);
    }
  }
  let result = await blub();
  console.log('result: ' + result);
}

test();
 
async/await hat noch andere Vorteile, wie z.B. sinvolle stack traces und damit verbunden wesentlich angenehmeres debugging, die Möglichkeit try catch zu nutzen (auch im Mix mit synchronem Code) und mit der neusten V8-Engine sogar eine höhere Performance als "manuelle" Promises.

Oder auch so schöne sachen wie asynchrone generatoren in verbindung mit for await of.

Bei deinem Beispielcode wird blub() aber erst ausgeführt, nachdem du hochgezählt hast. Hier passiert also nichts "zwischenzeitlich".

Falls dich interessiert, wie das Behind the Scenes abläuft, kannst du dir z.B. mal das hier anschauen: https://v8.dev/blog/fast-async
 
Zuletzt bearbeitet:
Zurück
Oben