2
votes

Pourquoi les appels setInterval ne sont-ils pas limités pour les 4 premières exécutions?

Il est un fait connu que les délais d'expiration dans JavaScript sont limités toutes les 4 ms sur un onglet actif et toutes les 1000 ms sur un onglet inactif . Ce comportement peut légèrement changer, selon le navigateur et la configuration, mais c'est généralement le même.

Pour être complet, je citerai ici la partie pertinente:

Délai d'expiration limité à> = 4 ms

Dans les navigateurs modernes, les appels setTimeout () / setInterval () sont limités au minimum une fois toutes les 4 ms lorsque des appels successifs sont déclenchés en raison de l'imbrication des rappels (où le le niveau d'imbrication est d'au moins une certaine profondeur), ou après un certain nombre d'intervalles successifs.

Je voulais le prouver à quelqu'un en utilisant cet extrait de code sur une instance Chrome par défaut:

4ms have passed after starting the interval
8ms have passed after starting the interval
12ms have passed after starting the interval
16ms have passed after starting the interval
20ms have passed after starting the interval

Et presque chaque fois que j'ai exécuté ce code, j'ai obtenu cette sortie:

1ms have passed after starting the interval
2ms have passed after starting the interval
3ms have passed after starting the interval
4ms have passed after starting the interval
8ms have passed after starting the interval
12ms have passed after starting the interval
16ms have passed after starting the interval
20ms have passed after starting the interval

Comme on peut le voir, l'intervalle est (généralement) a été exécuté une fois par milliseconde les quatre premières fois, et toutes les> = 4 ms par la suite.

Pourquoi est-ce que pour les 4 premières exécutions, les appels ne sont pas limités? J'attendais cette sortie:

let beforeStartingTheInterval = Date.now();
let intervalId = setInterval(()=>{ 
  let msPassed = Date.now()-beforeStartingTheInterval;
  if (msPassed > 20) clearInterval(intervalId); // stop after 20 ms
  console.log( msPassed + "ms have passed after starting the interval")
  }
,0);

Ou au moins une qui a un minimum de 4ms entre deux exécutions quelconques (même les premières)


0 commentaires

4 Réponses :


0
votes

La réponse se trouve dans la documentation que vous avez liée à (c'est moi qui souligne)

Dans Chrome et Firefox, le 5ème appel de rappel successif est bloqué ; Pinces Safari au 6e appel; dans Edge c'est le 3ème. Gecko a commencé à traiter setInterval () comme ceci dans la version 56 (il l'a déjà fait avec setTimeout (); voir ci-dessous).


2 commentaires

Je n'ai pas vu cela comme le "pourquoi" je demande


@Adelin Pourquoi? Parce que c'est ainsi que cela est spécifié par les fabricants de navigateurs. Que dire de plus à ce sujet?



0
votes

Après avoir parcouru le Web un peu plus, j'ai trouvé qu'il s'agissait d'un Norme HTML5 :

Remarque: les minuteries peuvent être imbriquées; après cinq de ces minuteries imbriquées, cependant, l'intervalle doit être d'au moins quatre millisecondes.


0 commentaires

1
votes

Pourquoi est-ce que pour les 4 premières exécutions, les appels ne sont pas limités?

Je suppose que la première question à se poser est Pourquoi la minuterie est-elle ralentie du tout?

Eh bien, certaines choses pourraient être, que des minuteries aussi courtes sont

1) difficile à mettre en œuvre car vous devez soit utiliser une minuterie matérielle, soit vérifier l'heure à l'intérieur d'une boucle, pour être en mesure de planifier les temps avec précision, la boucle doit fonctionner très rapidement.

2) consommant beaucoup de batterie / temps de calcul

3) ne sont probablement pas du tout nécessaires car l'affichage est mis à jour environ toutes les 60 ips, soit toutes les 16 ms, donc si vous utilisez une minuterie qui tourne aussi vite, vous ne verrez pas réellement la sortie à cette vitesse.

La question suivante pourrait alors être Pourquoi utilise-t-on des minuteries aussi courtes?

Il y a en fait quelques bonnes raisons:

1) Pour différer une action après a) le bloc de code actuel, prenez le setState de React par exemple b) un rendu DOM

2) Pour exécuter une longue tâche "asynchrone" sur le thread principal sans bloquer l'interface utilisateur, en la libérant pendant une milliseconde.

Par conséquent, le navigateur a un problème lors du réglage de l'heure de la minuterie:

S'il limite l'heure de par exemple setState de 4 ms, la page peut se charger globalement plus lentement. S'il ne ralentit pas un setInterval qui s'exécute inutilement rapidement, il gaspille la batterie des utilisateurs (la plupart des utilisateurs sont sur un mobile ces jours-ci).

Par conséquent, il est logique que le navigateur exécute quelques minuteries très rapidement, de sorte que setTimeout (différé, 0) soit exécuté immédiatement, puis ralentit après quelques temps, pour réduire l'impact négatif de minuteurs de rendu / algorithmes de longue durée mal conçus.

Les "4 ms" après "5 fois" sont probablement le résultat équilibré de cette considération.


0 commentaires

0
votes

https://humanwhocodes.com/blog/ 2011/12/14 / minuterie-resolution-in-browser /

La plupart des navigateurs effectuent également une sorte de limitation de la minuterie en fonction de différentes conditions. L’intention est d’économiser la batterie au moment opportun - des moments où, en théorie, vous ne remarquerez pas la différence ou vous échangeriez volontiers contre une meilleure autonomie de la batterie sur un ordinateur portable ou un appareil mobile. Voici quelques circonstances dans lesquelles la résolution du minuteur change:


0 commentaires