Je sais que le async await
est la nouvelle Promise
de la ville et qu’il s’agit d’une nouvelle façon d’écrire du code asynchrone et je sais aussi que
Nous n'avons pas eu besoin d'écrire .then
, de créer une fonction anonyme pour gérer la réponse
Async/await
permet enfin de gérer les erreurs synchrones et asynchrones avec la même construction, bon vieux try/catch
La pile d'erreur renvoyée d'une chaîne promise
ne donne aucune idée de l'endroit où l'erreur s'est produite. Cependant, la pile d’erreur async/wait pointe sur la fonction qui contient l’erreur
ET SO ON ...
mais ici, j’ai fait un repère simple https://repl.it/repls/FormalAbandonedChimpanzee
Dans l’indice de référence, j’ai exécuté 2 boucles 1 million de fois . Dans la première boucle, j’appelle une fonction renvoyant 1dans une autre fonction, j’appelle une fonction qui renvoie 1 par exception.
le temps pris par la première boucle qui appelle une fonction qui renvoie 1 équivaut à près de la moitié de la fonction qui renvoie 1 comme erreur.
Ce qui montre que le temps pris par throw
est presque le double du temps pris par return
node v7.4 linux/AMD64
return takes 1.233seconds
1000000
throw takes 2.128seconds
1000000
Code de référence ci-dessous
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);
Votre repère n'a rien à voir avec la performance entre async/await
et les promesses brutes. Tout ce que je peux voir, c'est que lancer une erreur prend plus de temps à calculer. Ceci est prévu.
Retour à la question principale, faut-il utiliser async/await
plutôt que .then
avec des promesses brutes?
Gardez à l'esprit que async/await
n'est que du sucre syntaxique par rapport aux promesses brutes, de sorte qu'il ne devrait pas y avoir beaucoup d'impact sur les performances globales. Cependant, cela rend votre code plus linéaire, ce qui supprime une surcharge cognitive du développeur.
La conclusion est d'utiliser ce que vous préférez. Les promesses peuvent être multifonctionnelles, mais les nouvelles syntaxes ne le peuvent pas. Vous voudrez peut-être garder cela à l'esprit lorsque vous déciderez du style à utiliser.
Certains malentendus:
La pile d'erreur renvoyée d'une chaîne de promesses ne donne aucune idée de l'endroit où l'erreur s'est produite
Ce n'est pas vrai. Une vérification rapide avec:
function error() {
return new Promise(function(res, rej) {
res(undefined()); // uh oh
});
}
error().then(console.log, e => console.log("Uh oh!", e.stack));
affiche la pile d'erreur complète, y compris l'emplacement.
Comme la plupart des choses vont, la réponse est "ça dépend".
Avant de parler de performance, l’aspect le plus important est la maintenabilité du code et la limitation de async
/await
par rapport à raw Promise
.
async
/await
est un excellent moyen d'exécuter du code asynchrone séquentiellement, alors que Promise
vous permet d'exécuter du code asynchrone simultanément.
async function foo() {
const a = await backend.doSomething()
const b = await backend.doAnotherThing()
return a + b
}
Dans le code ci-dessus, backend.doAnotherThing()
ne sera exécuté que lorsque backend.doSomething()
sera retourné. D'autre part:
function foo() {
Promise.all([backend.doSomething(), backend.doAnotherThing()])
.then(([a, b]) => {
return a + b
})
}
exécutera les deux appels et attendra que les deux se terminent.
Comme vous l'avez mentionné à propos des avantages de async
/await
, personnellement, je l'utilise beaucoup. Sauf les cas ci-dessus.
Si vous avez besoin de performances et que vous avez besoin de vous, la différence de performances entre async
/await
et Promise
est plus importante que l’avantage en lisibilité de async
/await
sur Promise
, va de soi.
Tant que c'est un choix conscient, ça devrait aller.
MISE À JOUR: comme mentionné par Derek 會 功夫
Vous pouvez obtenir une exécution parallèle avec async
/await
en:
async function foo() {
const p1 = backend.doSomething()
const p2 = backend.doAnotherThing()
return await p1 + await p2
}
Construire sur la réponse de unional :
Vous pouvez obtenir le même comportement que Promise.all
avec async/await
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
}
Les tâches principales se déroulent simultanément et nous attendons que les deux tâches soient terminées avant de revenir. Voir aussi l'exemple MDN que j'ai écrit
Sur cette base, je ne suis pas sûr que l’utilisation directe de Promises sur async/await
présente un avantage en termes de performances.