web-dev-qa-db-fra.com

Pourquoi le code après l'attente ne s'exécute-t-il pas immédiatement? N'est-il pas censé être non bloquant?

Salut les gars, j'ai du mal à comprendre comment asynchroniser et attendre fonctionne en coulisses. Je sais que nous avons des promesses qui rendent notre code non bloquant en utilisant la fonction "alors", nous pouvons placer tout le travail que nous devons faire une fois la promesse résolue. et le travail que nous voulons faire en parallèle pour promettre de l'écrire en dehors de notre fonction d'alors. Le code devient donc non bloquant. Cependant, je ne comprends pas comment le asyncawait fait du code non bloquant.

async function myAsyncFunction() {
  try {
    let data = await myAPICall('https://jsonplaceholder.typicode.com/posts/1');
    // It will not run this line until it resolves await.
    let result = 2 + 2;
    return data;
  }catch (ex){
    return ex;
  }
}

Voir le code ci-dessus. Je ne peux pas avancer tant que l'appel API n'est pas résolu. Si cela rend mon code bloquant le code, comment est-il meilleur que promis? Ou y a-t-il quelque chose que j'ai manqué à propos de async et await? Où dois-je mettre mon code qui ne dépend pas de l'appel en attente? afin qu'il puisse continuer à fonctionner sans attendre la tenue de l'exécution?

J'ajoute un code Promise que je voudrais répliquer dans un exemple d'attente asynchrone.

function myPromiseAPI() {
  myAPICall('https://jsonplaceholder.typicode.com/posts/1')
    .then(function (data) {
        // data
    });
   // runs parallel
  let result = 2 + 2;
}
14
Rohail Najam

Tout comme son nom l'indique, le mot clé await fera "attendre" jusqu'à ce que sa promesse soit résolue avant d'exécuter la ligne suivante. L'intérêt de await est de faire attendre le code jusqu'à la fin de l'opération avant de continuer.

La différence entre ce code et le code de blocage est que le monde extérieur la fonction peut continuer à s'exécuter pendant que la fonction attend la fin des opérations asynchrones.

async et await ne sont que du sucre syntaxique en plus des promesses. Ils vous permettent d'écrire du code qui ressemble beaucoup au code synchrone ordinaire même s'il utilise des promesses sous les couvertures. Si nous traduisions votre exemple là-bas en quelque chose qui fonctionnait explicitement avec les promesses, cela ressemblerait à quelque chose comme:

function myAsyncFunction() {
  return myAPICall('https://jsonplaceholder.typicode.com/posts/1')
    .then(function (data) {
       let result = 2 + 2;
       return data;
    })
    .catch(function (ex) {
        return ex;
    });
}

Comme nous pouvons le voir ici, la ligne let result = 2 + 2; Est à l'intérieur d'un gestionnaire .then(), ce qui signifie qu'elle ne s'exécutera pas tant que myAPICall() ne sera pas résolu. C'est la même chose lorsque vous utilisez await. await résume simplement la .then() pour vous.

Une chose à garder à l'esprit (et je pense que le point que vous recherchez) est que vous n'avez pas à utiliser await tout de suite. Si vous avez écrit votre fonction comme ceci, vous pouvez exécuter votre ligne let result = 2 + 2; Immédiatement:

const timeout = 
    seconds => new Promise(res => setTimeout(res, seconds * 1000));

function myAPICall() {
  // simulate 1 second wait time
  return timeout(1).then(() => 'success');
}

async function myAsyncFunction() {
  try {
    console.log('starting');

    // just starting the API call and storing the promise for now. not waiting yet
    let dataP = myAPICall('https://jsonplaceholder.typicode.com/posts/1');

    let result = 2 + 2;

    // Executes right away
    console.log('result', result);

    // wait now
    let data = await dataP;

    // Executes after one second
    console.log('data', data);

    return data;
  } catch (ex) {
    return ex;
  }
}

myAsyncFunction();

Après quelques éclaircissements, je peux voir que ce que vous vouliez vraiment savoir, c'est comment éviter d'avoir à attendre deux opérations asynchrones une par une et à la place de les exécuter en parallèle. En effet, si vous utilisez un await après l'autre, le second ne démarrera pas avant la fin du premier:

const timeout = 
    seconds => new Promise(res => setTimeout(res, seconds * 1000));

function myAPICall() {
  // simulate 1 second wait time
  return timeout(1).then(() => 'success');
}

async function myAsyncFunction() {
  try {
    console.log('starting');

    let data1 = await myAPICall('https://jsonplaceholder.typicode.com/posts/1');
    // logs after one second
    console.log('data1', data1);

    let data2 = await myAPICall('https://jsonplaceholder.typicode.com/posts/2');
    // logs after one more second
    console.log('data2', data2);
  } catch (ex) {
    return ex;
  }
}

myAsyncFunction();

Pour éviter cela, ce que vous pouvez faire est démarrer les deux opérations asynchrones en les exécutant sans les attendre, en affectant leurs promesses à certaines variables. Ensuite, vous pouvez attendre les deux promesses:

const timeout = 
    seconds => new Promise(res => setTimeout(res, seconds * 1000));

function myAPICall() {
  // simulate 1 second wait time
  return timeout(1).then(() => 'success');
}

async function myAsyncFunction() {
  try {
    console.log('starting');
    // both lines execute right away
    let dataP1 = myAPICall('https://jsonplaceholder.typicode.com/posts/1');
    let dataP2 = myAPICall('https://jsonplaceholder.typicode.com/posts/2');

    let data1 = await dataP1;
    let data2 = await dataP2;

    // logs after one second
    console.log('data1', data1);
    console.log('data2', data2);
  } catch (ex) {
    return ex;
  }
}

myAsyncFunction();

Une autre façon de procéder consiste à utiliser Promise.all() avec une décomposition de tableau:

const timeout = 
    seconds => new Promise(res => setTimeout(res, seconds * 1000));

function myAPICall() {
  // simulate 1 second wait time
  return timeout(1).then(() => 'success');
}

async function myAsyncFunction() {
  try {
    console.log('starting');

    // both myAPICall invocations execute right away
    const [data1, data2] = await Promise.all([
        myAPICall('https://jsonplaceholder.typicode.com/posts/1'), 
        myAPICall('https://jsonplaceholder.typicode.com/posts/2'),
    ]);

    // logs after one second
    console.log('data1', data1);
    console.log('data2', data2);
  } catch (ex) {
    return ex;
  }
}

myAsyncFunction();
31
JLRishe