J'espère que je ne me ridiculiserai pas mais j'essaie de comprendre ce qui se passe dans ces deux lignes de code:
document.body.innerHTML = 'something';
alert('something else');
Ce que j'observe, c'est que l'alerte s'affiche avant que HTML n'ait été mis à jour (ou peut-être que la page n'a pas été rafraîchie / repeinte / quoi que ce soit)
Consultez ce codepen pour voir ce que je veux dire.
Veuillez noter que même la mise alert
en place setTimeout(..., 0)
n'aide pas. On dirait qu'il faut plus de boucles d'événements pour mettre innerHTML
à jour la page.
ÉDITER:
J'ai oublié de mentionner que j'utilise Chrome et je n'ai pas vérifié les autres navigateurs. Il semble qu'il ne soit visible que dans Chrome. Néanmoins, je suis toujours intéressé par la raison pour laquelle cela se produit.
javascript
html
google-chrome
dom
pièce de bar
la source
la source
Réponses:
La configuration de innerHTML est synchrone, tout comme la plupart des modifications que vous pouvez apporter au DOM. Cependant, le rendu de la page Web est une autre histoire.
(N'oubliez pas que DOM signifie "Document Object Model". Il s'agit simplement d'un "modèle", une représentation de données. Ce que l'utilisateur voit sur son écran est une image de ce à quoi ce modèle devrait ressembler. Ainsi, changer de modèle ne se fait pas instantanément changer l'image - la mise à jour prend un certain temps.)
L'exécution de JavaScript et le rendu de la page Web se produisent en fait séparément. Pour simplifier, tout d'abord le JavaScript de la page s'exécute (à partir de la boucle d'événements - regardez cette excellente vidéo pour plus de détails), puis après que le navigateur rend toute modification apportée à la page Web pour l'utilisateur de voir. C'est pourquoi le "blocage" est si important - l'exécution de code intensif en calcul empêche le navigateur de passer l'étape "exécuter JS" et de passer à l'étape "rendre la page", provoquant le gel ou le bégaiement de la page.
Le pipeline de Chrome ressemble à ceci:
Comme vous pouvez le voir, tout le JavaScript se produit en premier. Ensuite, la page est stylisée, mise en page, peinte et composée - le «rendu». Tout ce pipeline n'exécutera pas chaque image. Cela dépend des éléments de page modifiés, le cas échéant, et de la manière dont ils doivent être rendus.
Remarque:
alert()
est également synchrone et s'exécute pendant l'étape JavaScript, c'est pourquoi la boîte de dialogue d'alerte apparaît avant que vous ne voyiez les modifications apportées à la page Web.Vous pourriez maintenant demander "Attendez, qu'est-ce qui est exactement exécuté dans cette étape 'JavaScript' du pipeline? Est-ce que tout mon code s'exécute 60 fois par seconde?" La réponse est "non", et cela revient au fonctionnement de la boucle d'événements JS. Le code JS ne s'exécute que s'il est dans la pile - à partir d'éléments tels que les écouteurs d'événements, les délais d'attente, etc. Voir la vidéo précédente (vraiment).
https://developers.google.com/web/fundamentals/performance/rendering/
la source
Oui, c'est synchrone, car cela fonctionne (allez-y, saisissez-le dans votre console):
La raison pour laquelle vous voyez l'alerte avant de voir la page changer est que le rendu du navigateur prend plus de temps et n'est pas aussi rapide que votre javascript s'exécutant ligne par ligne.
la source
text
dans mon exemple) Cela répondra à votre question de savoir si c'est synchrone. Le rendu du navigateur par rapport à l'exécution de Javascript est pomme et oranges :)La
innerHTML
propriété réelle est mise à jour de manière synchrone, mais la mise à jour visuelle provoquée par cette modification se produit de manière asynchrone.Le rendu visuel du DOM est asynchrone dans Chrome et ne se produira qu'après que la pile de fonctions JavaScript actuelle se soit effacée et que le navigateur soit libre d'accepter un nouvel événement. D'autres navigateurs peuvent utiliser des threads séparés pour gérer le code JavaScript et le rendu du navigateur, ou ils peuvent laisser certains événements avoir la priorité pendant qu'une alerte stoppe l'exécution d'un autre événement.
Vous pouvez voir cela de deux manières:
Si vous ajoutez
for(var i=0; i<1000000; i++) { }
avant votre alerte, vous avez laissé au navigateur suffisamment de temps pour effectuer un rafraîchissement, mais ce n'est pas le cas, car la pile de fonctions n'a pas été effacée (elleadd
est toujours en cours d'exécution).Si vous retardez votre
alert
via unsetTimeout(function() { alert('random'); }, 1)
processus asynchrone , le processus de rafraîchissement pourra avancer la fonction retardée par setTimeout.0
, peut-être parce que Chrome donne la priorité à la file d'0
attente d'événements aux délais d' attente avant tout autre événement (ou au moins avant les événements de rafraîchissement).la source
setTimeout(func, 1)