Warum no-return-await vs. const x = waiting?

Lesezeit: 8 Minuten

Benutzeravatar von AturSams
AturSams

Was ist der Unterschied zwischen

return await foo()

Und

const t = await foo();
return t

http://eslint.org/docs/rules/no-return-await

  • Sie sollten die zweite Version wirklich nicht verwenden, da sie keinen Nutzen bringt. Die richtige Codezeile wäre return foo();

    – Igor

    28. Juni 2017 um 15:02


  • Warum heißt es also nicht? const x = await foo; return x sollte vermieden werden?

    – AturSams

    28. Juni 2017 um 15:12

  • @zehelvion – wahrscheinlich, weil es zur Transpile-Zeit schwierig ist, dies zu erkennen, aber beide Aussagen sind gleichwertig und sollten vermieden werden.

    – Igor

    28. Juni 2017 um 15:13


  • Schauen Sie sich diese Erklärung an no-return-await Regel

    – Bergi

    20. Juli 2017 um 9:20 Uhr

  • @Igor Der Vorteil von return await ist, dass man – bereits in V8 hinter einem Flag – einen vollständigen asynchronen Stacktrace erhält. Das liegt daran, dass der vollständige Stack immer noch leicht rekonstruierbar ist, solange die ursprüngliche Funktion noch nicht abgeschlossen ist. Ohne das awaitWenn Sie das Versprechen direkt zurückgeben, wäre die Funktion endgültig verschwunden, wenn die tatsächliche Funktion, die das Versprechen erstellt, tiefer im Aufrufstapel ausgelöst wird. Suche “Kostenfreie asynchrone Stack-Traces” An v8.dev/blog/fast-async

    – Mörre

    22. Juni 2019 um 19:45 Uhr

samanimes Benutzeravatar
samanime

Im Grunde, weil return await ist überflüssig.

Betrachten Sie es von einer etwas höheren Ebene aus, wie Sie tatsächlich verwenden async Funktion:

const myFunc = async () => {
  return await doSomething();
};

await myFunc();

Beliebig async Funktion wird bereits a zurückgeben Promiseund muss als behandelt werden Promise (entweder direkt als Promiseoder auch await-ing).

Wenn du await Innerhalb der Funktion ist es redundant, weil die Funktion außerhalb dies auch tun wird await Es gibt also keinen Grund, es nicht einfach zu senden Promise mitmachen und die äußere Sache damit befassen.

Es ist weder syntaktisch falsch noch inkorrekt und verursacht im Allgemeinen keine Probleme. Es ist einfach völlig überflüssig, weshalb der Linter darauf ausgelöst wird.

  • Ich bin mir nicht sicher, ob „Senden Sie das Versprechen weiter und lassen Sie das Äußere sich darum kümmern“ 100 % richtig ist. In meinen Tests wird ein neues Versprechen erstellt, indem sowohl das Versprechen direkt zurückgegeben wird als auch darauf gewartet wird, dass der Wert dann zurückgegeben wird: function waitForN(time) { return new Promise((resolve, reject) => { setTimeout(() => { reject(new Error('Rejected')); }, time); }); } async function testing() { myPromise = waitForN(1000); myPromise.catch(error => console.log(error)); return myPromise; } Dies führt zu einem gefangenen und einem nicht gefangenen Versprechen.

    – TigerBear

    20. August 2018 um 15:02 Uhr

  • @samanime Siehe meinen Kommentar unter OPs Frage. Seit der Einführung von „Zero-Cost Async Stack Traces“ in V8 return await unterscheidet sich erheblich von der Rückgabe des Versprechens: Sie erhalten einen Stack-Trace (zumindest in V8, ab sofort)!

    – Mörre

    22. Juni 2019 um 19:47 Uhr

  • @samanime Nicht in meinen Tests. Ich erhalte einen Stacktrace. Das ist genau das, was sie behaupten. Wenn Sie nicht bekommen, was sie behaupten, sollten Sie eine Anzeige erstatten. Hüten Sie sich auch vor zu einfachen Tests. Versprechen und ihre auf „Mikrotask“-Warteschlangen basierende Implementierung verhalten sich nicht gleich, wenn sie nicht wirklich asynchron sind.

    – Mörre

    23. Juni 2019 um 13:51 Uhr


  • @samanime Ich beziehe mich auf meinen vorherigen Kommentar … was auch immer Sie testen, es ist nicht diese Funktionalität. Es funktioniert, ich habe es versucht – Google hat es versucht. Oder wenn nicht, liegt in Ihrem Setup ein Fehler vor. Finden Sie es oder melden Sie es.

    – Mörre

    23. Juni 2019 um 19:09 Uhr


  • mit try{ return await foo() } finally { /* some code */ } es macht aber Sinn. Entferne den await Ändern Sie die Semantik in „Nachdem Sie das Versprechen erhalten haben, tun Sie dies, was auch immer passiert“ anstelle der beabsichtigten „Tue dies, nachdem das Versprechen erfüllt (aufgelöst oder abgelehnt) wurde“. Es ist ziemlich leicht, ein solches Konstrukt zu übersehen.

    – Programmatiken

    10. Juni 2021 um 8:31 Uhr

Bamiehs Benutzeravatar
Bamieh

Benutzen return await bietet einige neu eingeführte Vorteile in der v8-Engine, die von Node.js, Chrome und einigen anderen Browsern verwendet wird:

v8 führte ein --async-stack-traces Flag, das ab V8 v7.3 standardmäßig aktiviert ist (Node.js v12.0.0).

Diese Flags bieten eine verbesserte Entwicklererfahrung, indem sie die Eigenschaft „Error-Stack“ mit dem Stack-Trace für asynchrone Funktionsaufrufe anreichern.

async function foo() {
  return bar();
}

async function bar() {
  await Promise.resolve();
  throw new Error('BEEP BEEP');
}

foo().catch(error => console.log(error.stack));


Error: BEEP BEEP
    at bar (<anonymous>:7:9)

Bitte beachten Sie dies telefonisch return bar(); foo() Der Funktionsaufruf erscheint überhaupt nicht im Fehlerstapel. Ändern Sie es in return await bar(); gibt eine viel bessere Ausgabe des Fehlerstapels:

async function foo() {
  return await bar();
}
foo();

Error: BEEP BEEP
    at bar (<anonymous>:7:9)
    at async foo (<anonymous>:2:10)

Dies ermöglicht in der Tat eine viel bessere Fehlerstapelverfolgung, und das ist auch der Fall Wir empfehlen Ihnen dringend, immer auf Ihre Versprechen zu warten.

Darüber hinaus übertrifft async/wait jetzt handgeschriebene Versprechen:

async/await übertrifft jetzt handgeschriebenen Promise-Code. Die wichtigste Erkenntnis hierbei ist, dass wir den Overhead asynchroner Funktionen durch das Patchen der Spezifikation erheblich reduziert haben – nicht nur in V8, sondern über alle JavaScript-Engines hinweg. Quelle

Lesen Sie mehr über diese Änderungen im v8.dev-Blog: https://v8.dev/blog/fast-async#improved-developer-experience

  • Dies scheint nicht zu erklären, warum const x = await foo() ist besser als return await foo() wenn das der Fall ist?

    – AturSams

    28. Juni 2017 um 15:09

  • Nun, wenn Sie nur const x = und dann return tun, wird es in der Lage sein, es zu erkennen, aber ich verstehe die Idee. Es ist genau das Gleiche und der Grund, warum nicht davor gewarnt wird, ist, dass es sich nicht mit der Erkennung des komplizierteren Anwendungsfalls befassen möchte.

    – AturSams

    29. Juni 2017 um 10:09

  • „Innerhalb einer asynchronen Funktion ist Return Wait nutzlos“ — nicht, wenn die return Aussage ist innerhalb von a try ... catch Block. In diesem Fall können Sie durch Warten alle vorhandenen Fehler beheben.

    – John Weisz

    24. August 2017 um 11:17 Uhr

  • „Return Wait“ ist SEHR nützlich, wenn Sie Code auf einer aktuellen Version von V8 ausführen (z. B. aktuelles node.js) – wenn Sie vor der Rückkehr warten, kann V8 vollständig asynchron komponieren. Stack-Traces (ohne „Kosten“, da der Kontext der aufrufenden Funktion aufgrund der Funktion „kostenlos“ verfügbar ist await).

    – Mörre

    14. Juli 2019 um 8:09

  • @Bamieh v8.dev/blog/fast-async – Scrollen Sie nach unten zu „Kostenlos“; Beachten Sie, dass die Funktion jetzt standardmäßig aktiviert ist, z. B. in aktuellen Versionen von node.js und Chrome.

    – Mörre

    16. Juli 2019 um 11:14 Uhr


Benutzeravatar von Edvard Chen
Edvard Chen

Weil du es einfach kannst

async function() {
  return foo();
}

Das zurückgegebene Ergebnis von async function ist immer so Promiseegal ob Sie den genauen oder einen anderen Wert zurückgeben Promise Objekt innerhalb des Funktionskörpers

  • Das ist hier die beste Antwort!!

    – Yoni Rabinovitch

    1. August 2018 um 8:24

  • anstatt return await foo()Nur return foo().

    – jmazin

    13. März 2019 um 16:19 Uhr


  • @YoniRabinovitch Nicht mehr. „Return Wait“ ist SEHR nützlich, wenn Sie Code auf einer aktuellen Version von V8 ausführen (z. B. aktuelles node.js) – wenn Sie vor der Rückkehr warten, kann V8 vollständig asynchron komponieren. Stack-Traces (ohne „Kosten“, da der Kontext der aufrufenden Funktion aufgrund der Funktion „kostenlos“ verfügbar ist await).

    – Mörre

    14. Juli 2019 um 8:09

Benutzeravatar von Tamas Hegedus
Tamas Hegedus

Es scheint, dass viele über die Nützlichkeit von diskutieren return await in den Kommentaren. Lassen Sie mich eine Demonstration hinzufügen, die zeigt, wie der Stacktrace beeinflusst wird.

Meiner Meinung nach überspringen await ist ein fehlgeleiteter Versuch einer gewissen „Optimierung“, bei dem 6 Zeichen und eine Mikrotask eingespart werden (BEARBEITEN: ShortFuse hat gerade gezeigt, dass es in der aktuellen Version 8 tatsächlich nicht speichert, sondern eine Mikrotask hinzufügt), auf Kosten von Stacktraces, Try-Catches, Refactorability usw Codekonsistenz. Die Faustregel ist einfach: Führen Sie einen asynchronen Aufruf durch und warten Sie darauf (es sei denn, Sie führen ausgefallene Dinge wie Parallelität oder asynchrones Caching aus). Ich glaube, wir sollten uns an die Faustregel halten und stets verwenden return awaitund schalten Sie das aus no-return-await Eslint-Regel.

kleine Demo:

async function main() {
  console.log("\nStatcktrace with await shows testStackWithAwait:");
  await testStackWithAwait().catch(logStack);
  console.log("\nStatcktrace without await hides testStackWithoutAwait:");
  await testStackWithoutAwait().catch(logStack);
  console.log("\nFinally happens before try block ends without await:");
  await testFinallyWithoutAwait();
}

async function fnThatThrows() {
  await delay(1);
  throw new Error();
}

async function testStackWithoutAwait() {
  return fnThatThrows(); // bad
}

async function testStackWithAwait() {
  return await fnThatThrows(); // good
}

async function fnThatLogs() {
  await delay(1);
  console.log('inside');
}

async function testFinallyWithoutAwait() {
  try {
    return fnThatLogs(); // bad
  } finally {
    console.log('finally');
  }
}

function logStack(e) {
  console.log(e.stack);
}

function delay(timeout, value) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(value);
    }, timeout);
  });
}

main().catch(console.error);

Unter Chrome 103 unter Windows erhalte ich die folgenden Protokolle:

Statcktrace with await shows testStackWithAwait:
Error
    at fnThatThrows (https://stacksnippets.net/js:23:9)
    at async testStackWithAwait (https://stacksnippets.net/js:31:10)
    at async main (https://stacksnippets.net/js:14:3)

Statcktrace without await hides testStackWithoutAwait:
Error
    at fnThatThrows (https://stacksnippets.net/js:23:9)
    at async main (https://stacksnippets.net/js:16:3)

Finally happens before try block ends without await:
finally
inside

Benutzeravatar von Husniddin Qurbonboyev
Husniddin Qurbonboyev

Der wesentliche Unterschied zwischen return asyncFunc und return waiting Promise.resolve() besteht darin, dass Sie durch Befolgen des zweiten Ansatzes einen Fehler abfangen können, wenn in der async-Funktion etwas nicht stimmt.

function afunction() {
  return asyncFun();
}
   
// with await
async function afunction() {
  try {
    return await asyncFun();
  } catch(err) {
    handleError(err);
    // return error result;
  }
}

   
    

Benutzeravatar von Yoshio H. Palacios
Yoshio H. Palacios

Oh, ich denke, das ist leicht zu verstehen. Wir geben „await“ ein, wenn wir auf einen bestimmten Wert warten, um einen Prozess fortzusetzen. Wenn der Prozess abgeschlossen ist (siehe Rückgabe), benötigen wir die Wait-Syntax nicht mehr.

return await foo(); //is redundant
return foo(); //is the correct way

1453390cookie-checkWarum no-return-await vs. const x = waiting?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy