web-dev-qa-db-fra.com

Fonction asynchrone sans attente en Javascript

J'ai deux fonctions a et b asynchrones, la première sans await et la dernière avec await. Ils enregistrent tous deux quelque chose sur la console et retournent undefined. Après avoir appelé l'une des fonctions, j'enregistre un autre message et vérifie si le message est écrit avant ou après l'exécution du corps de la fonction.

function someMath() {
  for (let i = 0; i < 3000000; i++) { Math.sqrt(i**5) }
}

function timeout(n) {
   return new Promise(cb => setTimeout(cb, n))
}

// ------------------------------------------------- a (no await)
async function a() {
  someMath()
  console.log('in a (no await)')
}

// ---------------------------------------------------- b (await)
async function b() {
  await timeout(100)
  console.log('in b (await)')
}

clear.onclick = console.clear

aButton.onclick = function() {
  a()
  console.log('after a (no await) call')
}

bButton.onclick = function() {
  b()
  console.log('after b (await) call')
}
<button id="aButton">test without await</button>
<button id="bButton">test with await</button>
<button id="clear">clear console</button>

Si vous lancez test sans await, la fonction semble fonctionner comme si elle était synchrone. Mais avec await, les messages sont inversés car la fonction est exécutée de manière asynchrone.

Ma question est donc la suivante: comment javascript exécute-t-il async fonctionne-t-il en l'absence de mot clé await?


Cas d'utilisation réel: J'ai un mot clé await qui est exécuté de manière conditionnelle et j'ai besoin de savoir si la fonction est exécutée de manière synchrone ou non. afin de rendre mon élément:

async function initializeComponent(stuff) {
   if (stuff === undefined)
      stuff = await getStuff()
   // initialize

   if (/* context has been blocked */)
       renderComponent() // render again if stuff had to be loaded
}

initializeComponent()
renderComponent()

P.S: title contient le mot clé javascript pour éviter toute confusion avec les mêmes questions dans d'autres langues (c'est-à-dire tilisation asynchrone sans attendre )

29
Ulysse BN

de mozilla doc:

Une fonction asynchrone peut contenir une expression en attente, qui suspend l'exécution de la fonction async, attend la résolution de la promesse transmise, puis reprend l'exécution de la fonction asynchrone. et retourne la valeur résolue.

Comme vous l'avez supposé, si aucune attente n'est présente, l'exécution n'est pas suspendue et votre code sera alors exécuté de manière synchrone.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function#Description

24
Karim

Tout est synchrone jusqu'à l'exécution d'une fonction asynchrone Javascript. En utilisant async-wait, await est asynchrone et tout ce qui suit est placé dans la file d'attente des événements. Similaire à .then().

Pour mieux expliquer, prenons cet exemple:

function main() {
  return new Promise( resolve => {
    console.log(3);
    resolve(4);
    console.log(5);
  });
}

async function f(){
    console.log(2);
    let r = await main();
    console.log(r);
}

console.log(1);
f();
console.log(6);

Comme await est asynchrone et reste tout est synchrone y compris la promesse donc la sortie est

1
2
3
5
6
// Async happened, await for main()
4

Un comportement similaire de main() est également sans promesse:

function main() {
    console.log(3);
    return 4;
}

async function f(){
    console.log(2);
    let r = await main();
    console.log(r);
}

console.log(1);
f();
console.log(5);

Sortie:

1
2
3
5
// Asynchronous happened, await for main()
4

Si vous supprimez simplement await, toute la fonction async sera synchrone.

function main() {
    console.log(3);
    return 4;
}

async function f(){
    console.log(2);
    let r = main();
    console.log(r);
}

console.log(1);
f();
console.log(5);

Sortie:

1
2
3
4
5
10
NAVIN

La fonction est exécutée de la même manière avec ou sans await. Ce que await fait, c'est attendre automatiquement que la promesse retournée par la fonction soit résolue.

await timeout(1000);
more code here;

est à peu près équivalent à:

timeout(1000).then(function() {
    more code here;
});

Le async function déclaration fait simplement que la fonction retourne automatiquement une promesse qui est résolue au retour de la fonction.

8
Barmar