Maison  >  Article  >  interface Web  >  Des promesses qui doivent être vraiment comprises

Des promesses qui doivent être vraiment comprises

coldplay.xixi
coldplay.xixiavant
2020-09-07 13:30:062014parcourir

Des promesses qui doivent être vraiment comprises

Recommandations d'apprentissage associées : Tutoriel d'apprentissage javascript

Promesse Concernant l'API, tout le monde devrait pouvoir l'utiliser avec compétence, mais vous pouvez encore avoir des angles morts en matière de connaissances liés aux microtâches.

Connaissances préalables

Avant de commencer le texte principal, donnons d'abord le ton à l'avance pour une partie du contenu impliqué dans cet article.

Promesse Quelles API impliquent des microtâches ?

Dans Promise, seuls les rappels qui doivent être exécutés après que des changements d'état soient impliqués sont considérés comme des microtâches, telles que then, catch, finally. Toutes les autres exécutions de code sont des macrotâches (implémentation synchrone).

Des promesses qui doivent être vraiment comprises

Dans l'image ci-dessus, le bleu représente une exécution synchrone et le jaune représente une exécution asynchrone (jetée dans la file d'attente des microtâches).

Quand ces microtâches seront-elles ajoutées à la file d'attente des microtâches ?

Examinons ce problème selon la spécification ecma :

  • Si le statut de la promesse est en attente à ce moment-là, alors les rappels réussis ou échoués seront ajoutés à [[PromiseFulfillReactions]] et [[PromiseRejectReactions]] Moyen. Si vous avez examiné le code manuscrit de Promise, vous devriez pouvoir constater qu'il existe deux tableaux stockant ces fonctions de rappel.

  • Si le statut de la promesse n'est pas en attente à ce moment-là, le rappel deviendra des tâches promises, qui sont des microtâches.

Après avoir compris les connaissances ci-dessus, le film principal commence.

De même, différentes micro-tâches sont exécutées

Basique

Promise.resolve()
  .then(() => {    console.log("then1");    Promise.resolve().then(() => {      console.log("then1-1");
    });
  })
  .then(() => {    console.log("then2");
  });复制代码

Tout le monde devrait pouvoir obtenir la bonne réponse à partir du code ci-dessus : then1 → then1-1 → then2 .

Bien que then soit exécuté de manière synchrone et que le statut ait changé. Mais cela ne signifie pas que chaque fois que nous rencontrons then, nous devons lancer son rappel dans la file d'attente des microtâches, nous devons plutôt attendre la fin du rappel de then, puis effectuer l'opération correspondante en fonction de la situation. .

Sur cette base, nous pouvons tirer la première conclusion : Dans l'appel en chaîne, seulement après l'exécution du rappel du then précédent, ce qui suit then seront ajoutés à la file d'attente des microtâches.

Intermédiaire

Tout le monde sait qu'après

, le rappel dans Promise resolve entrera immédiatement dans la file d'attente des microtâches. then

Alors, à votre avis, quel sera le résultat du code suivant ?

let p = Promise.resolve();

p.then(() => {  console.log("then1");  Promise.resolve().then(() => {    console.log("then1-1");
  });
}).then(() => {  console.log("then1-2");
});

p.then(() => {  console.log("then2");
}); 
复制代码

Selon notre compréhension initiale, il n'est pas difficile de conclure que

sera sorti après then2, mais la situation réelle est le contraire. then1-1

Sur cette base, nous tirons la deuxième conclusion :

Le début de chaque appel en chaîne entrera d'abord dans la file d'attente des microtâches dans l'ordre.

Ensuite, changeons la méthode d'écriture :

let p = Promise.resolve().then(() => {  console.log("then1");  Promise.resolve().then(() => {    console.log("then1-1");
  });
}).then(() => {  console.log("then2");
});

p.then(() => {  console.log("then3");
});复制代码

Le code ci-dessus a en fait un piège,

renverra une nouvelle promesse à chaque fois, et le then à ce moment-là le temps n'est plusp est généré par le dernier Promise.resolve(), donc then doit être imprimé après then3. then2

Au fait, nous pouvons également optimiser la conclusion à laquelle nous sommes arrivés auparavant :

Le début de chaque appel en chaîne de la même promesse entrera d'abord dans la file d'attente des microtâches dans l'ordre.

Avancé

Vous pouvez deviner quand

sera imprimé ? then1-2

Promise.resolve()
  .then(() => {    console.log("then1");    Promise.resolve()
      .then(() => {        console.log("then1-1");        return 1;
      })
      .then(() => {        console.log("then1-2");
      });
  })
  .then(() => {    console.log("then2");
  })
  .then(() => {    console.log("then3");
  })
  .then(() => {    console.log("then4");
  });复制代码

Cette question est vraiment simple. Rappelez-vous la première conclusion pour obtenir la réponse. Voici l'analyse :

  • Première fois

    Suivant A resolve le rappel entre dans la file d'attente des microtâches et est exécuté Après avoir imprimé thenthen1

  • pour la deuxième fois

    , le premier rappel interne resolve entre dans la file d'attente des microtâches, à ce moment. , tous les premiers rappels then externes ont été exécutés et le deuxième rappel then externe doit être inséré dans la file d'attente des microtâches. then

  • Exécutez la microtâche, imprimez

    et then1-1, puis insérez les rappels dans les then2 suivants dans la file d'attente des microtâches then

  • Exécutez la micro-tâche, imprimez

    et then1-2, le contenu suivant ne sera pas expliqué un par unthen3

Ensuite nous modifions

, le résultat sera grand Pas pareil : return 1

Promise.resolve()
  .then(() => {    console.log("then1");    Promise.resolve()
      .then(() => {        console.log("then1-1");        return Promise.resolve();
      })
      .then(() => {        console.log("then1-2");
      });
  })
  .then(() => {    console.log("then2");
  })
  .then(() => {    console.log("then3");
  })
  .then(() => {    console.log("then4");
  });复制代码

Quand on

, devinez quand return Promise.resolve() sera imprimé ? then1-2

La réponse est la dernière imprimée.

Pourquoi y a-t-il un si grand changement dans l'ordre d'exécution des microtâches alors qu'il y a

choses différentes dans then ? Voici l'analyse de l'auteur. return

PS:then 返回一个新的 Promise,并且会用这个 Promise 去 resolve 返回值,这个概念需要大家先了解一下。

根据 Promise A+ 规范

根据规范 2.3.2,如果 resolve 了一个 Promise,需要为其加上一个 thenresolve

if (x instanceof MyPromise) {  if (x.currentState === PENDING) {
  } else {
    x.then(resolve, reject);
  }  return;
}复制代码

上述代码节选自手写 Promise 实现。

那么根据 A+ 规范来说,如果我们在 then 中返回了 Promise.resolve 的话会多入队一次微任务,但是这个结论还是与实际不符的,因此我们还需要寻找其他权威的文档。

根据 ECMA - 262 规范

根据规范 25.6.1.3.2,当 Promise resolve 了一个 Promise 时,会产生一个NewPromiseResolveThenableJob,这是属于 Promise Jobs 中的一种,也就是微任务。

This Job uses the supplied thenable and its then method to resolve the given promise. This process must take place as a Job to ensure that the evaluation of the then method occurs after evaluation of any surrounding code has completed.

并且该 Jobs 还会调用一次 then 函数来 resolve Promise,这也就又生成了一次微任务。

这就是为什么会触发两次微任务的来源。

最后

文章到这里就完结了,大家有什么疑问都可以在评论区提出。

想了解更多编程学习,敬请关注php培训栏目!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer