Ich weiß, dass der async await
die neue Promise
in der Stadt ist, und es ist eine neue Art, asynchronen Code zu schreiben, und das weiß ich auch
Wir mussten nicht .then
schreiben, sondern eine anonyme Funktion erstellen, um die Antwort zu bearbeiten
Async/await
macht es endlich möglich, sowohl synchrone als auch asynchrone Fehler mit demselben Konstrukt zu behandeln, also gut alt try/catch
Der von einer promise
-Kette zurückgegebene Fehlerstapel gibt keinen Hinweis darauf, wo der Fehler aufgetreten ist. Der Fehlerstack von async/await verweist jedoch auf die Funktion, die den Fehler enthält
UND SO EIN ...
aber hier habe ich eine einfache Benchmark erstellt https://repl.it/repls/FormalAbandonedChimpanzee
Im Benchmark habe ich 1 Million Mal 2 Schleifen ausgeführt. In der ersten Schleife rufe ich eine Funktion auf, die 1 Zurückgibt. In einer anderen Funktion rufe ich eine Funktion auf, die als Ausnahme 1 auslöst .
die Zeit, die die erste Schleife benötigt, die eine Funktion aufruft, die 1 zurückgibt, ist fast die Hälfte der Funktion, die 1 als Fehler auslöst.
Dies zeigt, dass die Zeit von throw
fast doppelt so lang ist wie die von return
.
node v7.4 linux/AMD64
return takes 1.233seconds
1000000
throw takes 2.128seconds
1000000
Benchmark-Code unten
function f1() {
return 1;
}
function f2() {
throw 1;
}
function parseHrtimeToSeconds(hrtime) {
var seconds = (hrtime[0] + (hrtime[1] / 1e9)).toFixed(3);
return seconds;
}
var sum = 0;
var start = 0;
var i = 0;
start = process.hrtime();
for (i = 0; i < 1e6; i++) {
try {
sum += f1();
} catch (e) {
sum += e;
}
}
var seconds = parseHrtimeToSeconds(process.hrtime(start));
console.log('return takes ' + seconds + 'seconds');
console.log(sum);
sum = 0;
start = process.hrtime();
for (i = 0; i < 1e6; i++) {
try {
sum += f2();
} catch (e) {
sum += e;
}
}
seconds = parseHrtimeToSeconds(process.hrtime(start));
console.log('throw takes ' + seconds + 'seconds');
console.log(sum);
Ihr Benchmark hat nichts mit der Performance zwischen async/await
und rohen Versprechen zu tun. Alles was ich sehen kann ist, dass das Berechnen eines Fehlers länger dauert. Das wird erwartet.
Zurück zur Hauptfrage: Verwenden Sie async/await
anstelle von .then
mit reinen Versprechen.
Denken Sie daran, dass async/await
nur syntaktischer Zucker über rohen Versprechen ist, daher sollte die Gesamtleistung nicht wesentlich beeinflusst werden. Allerdings wird Ihr Code dadurch linearer, was dem Entwickler viel kognitiven Aufwand erspart.
Die Schlussfolgerung ist, was Sie bevorzugen. Versprechen können mehrfach gefüllt werden, neue Syntaxe jedoch nicht. Daher sollten Sie dies bei der Auswahl des zu verwendenden Stils beachten.
Ein Missverständnis:
Der von einer Versprechungskette zurückgegebene Fehlerstapel gibt keinen Hinweis darauf, wo der Fehler aufgetreten ist
Das ist nicht wahr. Ein kurzer Check bei:
function error() {
return new Promise(function(res, rej) {
res(undefined()); // uh oh
});
}
error().then(console.log, e => console.log("Uh oh!", e.stack));
zeigt den gesamten Fehlerstapel einschließlich der Position an.
Wie die meisten Dinge gehen, lautet die Antwort "es kommt darauf an".
Bevor wir über Leistung sprechen, ist der wichtigste Aspekt die Wartbarkeit des Codes und die Einschränkung von async
/await
im Vergleich zu raw Promise
.
Mit async
/await
können Sie asynchronen Code sequentiell ausführen. Mit Promise
können Sie asynchronen Code gleichzeitig ausführen.
async function foo() {
const a = await backend.doSomething()
const b = await backend.doAnotherThing()
return a + b
}
Im obigen Code wird backend.doAnotherThing()
erst ausgeführt, nachdem backend.doSomething()
zurückgekehrt ist. Auf der anderen Seite:
function foo() {
Promise.all([backend.doSomething(), backend.doAnotherThing()])
.then(([a, b]) => {
return a + b
})
}
führt beide Aufrufe aus und wartet, bis beide abgeschlossen sind.
Wie Sie bereits über die Vorteile von async
/await
gesprochen haben, benutze ich sie persönlich ausführlich. Mit Ausnahme der oben genannten Fälle.
Wenn Sie Leistung benötigen und für Sie wichtig sind, ist der Leistungsunterschied zwischen async
/await
und Promise
wichtiger als der Lesbarkeitsvorteil von async
/await
über Promise
.
Solange es eine bewusste Entscheidung ist, sollte es Ihnen gut gehen.
UPDATE: wie von Derek mentioned erwähnt
Sie können die parallele Ausführung mit async
/await
folgendermaßen erhalten:
async function foo() {
const p1 = backend.doSomething()
const p2 = backend.doAnotherThing()
return await p1 + await p2
}
Aufbauend auf die Antwort von unional :
Sie können dasselbe Verhalten wie Promise.all
mit async/await
erreichen.
function foo() {
Promise.all([backend.doSomething(), backend.doAnotherThing()])
.then(([a, b]) => {
return a + b
})
}
async function foo() {
const a = backend.doSomething()
const b = backend.doAnotherThing()
return await a + await b
}
Backend-Aufgaben finden gleichzeitig statt und wir warten darauf, dass beide abgeschlossen sind, bevor wir zurückkehren. Siehe auch das MDN-Beispiel, das ich geschrieben habe
Aufgrund dessen bin ich nicht sicher, ob es einen Leistungsvorteil für die direkte Verwendung von Promises gegenüber async/await
gibt.