9
votes

En utilisant SettimeOut pour améliorer la réactivité

Lorsque vous souhaitez améliorer la performance d'une page, une technique que je n'ai pas entendue mentionnée avant d'utiliser SettimeOut pour empêcher JavaScript de tenir le rendu d'une page.

Par exemple, imaginez que nous avons une pièce de bonne consommation de temps de JQuery Inline avec le HTML: P>

setTimeout(function() {
    $('input').click(function () {
        // Do stuff
    })
}, 100);


5 commentaires

Je suppose que cela dépendra fortement du navigateur si cela sera plus rapide ou non. Avez-vous aspiré un rendu avec cela?


Settimeout n'apparaît pas un nouveau fil. Au lieu de cela, les files d'attente pour le fil unique de l'exécution à un moment donné de l'avenir.


En variante, envisagez de placer votre temps de consommation de temps à l'intérieur d'un $ (document) .Ready (fonction (fonction () {...});


Cela améliore réactivité , pas performance .


Faites attention à la fréquence à laquelle vous utilisez le Settimeout idiome (voir @ Commentaire de Ephémient). Les gens de Google ont fait une grande pièce sur [AB] en utilisant des minuteries avec des conséquences ironiquement lentes: googlecode.blogspot.com/2009/07/... .


3 Réponses :


-1
votes

Vous êtes correct, il y a une plus grande chance d'un clic "manqué", mais avec une faible valeur de délai d'attente, sa assez improbable.


0 commentaires

12
votes

La technique réelle consiste à utiliser Settimeout avec un temps de 0.

Ceci fonctionne car JavaScript est unifaminé. Un délai d'attente ne provoque pas le navigateur d'un autre fil, il ne garantit pas que le code s'exécutera à l'heure spécifiée. Cependant, le code sera exécuté lorsque:

  1. le temps spécifié s'est écoulé.
  2. Le contrôle d'exécution est remis au navigateur.

    appelant donc settimeout avec un temps de 0 peut être considéré comme céder temporairement au navigateur.

    Cela signifie que si vous avez un code de course à long terme, vous pouvez Simulez la multi-threading en cédant régulièrement avec un Settimeout . Votre code peut ressembler à quelque chose comme ceci: xxx


    note : alors qu'il est utile de connaître cette technique dans Scénariossome , je doute fort que vous en aurez besoin dans la situation que vous décrivez (attribuant des gestionnaires d'événements sur DOM Prêt). Si la performance est en effet un problème, je suggère d'examiner les moyens d'améliorer la performance forte en modifiant le sélecteur.

    Par exemple si vous n'avez qu'un seul formulaire sur la page qui contient s, puis donnez le une carte d'identité et utilisez $ ("# Entrée personnelle") . .


8 commentaires

Bien que je n'ai pas testé cela avec le groupe de navigateurs le plus moderne, j'ai rencontré des problèmes dans le passé avec l'utilisation de 0 comme délai d'attente: un navigateur était en train de courir à une exécution synchrone. J'utilise donc toujours 1.


@Ates, je ne suis pas couru dans cela avant, mais c'est très intéressant, merci pour l'information.


@Ates: Ce que vous décrivez, il faut jamais arriver. Quel navigateur? Quel contexte?


@Crescent Frais: Comment pouvez-vous être si sûr? Sauf si bien sûr, vous savez par cœur les internes du moteur JS de tous les navigateurs à ce jour ... je me souviens juste de voir cela au moins une fois. Je ne me souviens pas exactement de quel navigateur ni quel contexte ou quelle année, mais je suis sûr que je l'ai vu.


@Crescent Frais: En outre, juste pour clarifier, en "le traitant comme synchrone", je ne voulais pas dire qu'il a inlisé le rappel: il a simplement exécuté la fonction à l'extrémité de la queue du fil JS actuel, sans céder au navigateur ( ou dom). J'aimerais avoir le moyen de tester cela à nouveau avec quelques navigateurs plus âgés, mais je ne le fais pas. Nous devrons vivre avec mon anecdote à moins que vous n'ayez Preuve que cela est impossible. Cela dit, j'avoue que j'avais toujours une chance que mon interprétation du symptôme était fausse.


Yikes! code.google.com/p/chromium/issues/detail?id= 888 "Settimeout (..., 0) incendie trop rapidement" Bug rapporté par l'homme lui-même. Je suppose que je ne rêvais pas ...;)


@Ates, le rapport de bogue (et les commentaires suivants) ne mentionne pas la synchronicité, qui est la principale chose. Le fait que la minuterie de chrome n'a pas de minimum (bien que cela a toujours 1 ms) ne signifie pas que le code ne cède pas au navigateur.


@ Box9: Oui, ce rapport de bogue n'a pas l'air sans rapport. Il est probable que j'avais fait que l'observation due à des modifications de DOM ne soit pas prête quand je m'attendais à ce qu'ils soient. Je n'aurais pas été coché par une minuterie courte (1 ms contre 10+ ms comme celle mentionnée dans ce rapport de bogue), mais avec certaines erreurs d'exécution dues à ne pas pouvoir accéder à un nouvel élément DOM que je m'attends à être prêt. Quoi qu'il en soit ... Ma réclamation ne peut aller au-delà d'un niveau anecdote / spéculation car je n'ai aucun moyen de le prouver. Donc, je vais juste accepter la défaite et laisser aller pour le moment :)



3
votes

Settimeout () peut être utilisé pour améliorer le temps de chargement "perçu" - mais pas la façon dont vous l'avez montré. Utilisation de Settimeout () Ne provoque pas que votre code fonctionne dans un fil séparé. Au lieu de Settimeout () Il suffit de le fil de retour sur le navigateur pour (environ) le temps spécifié. Quand il est temps que votre fonction soit exécutée, le navigateur donnera le fil de retour au moteur JavaScript. En JavaScript, il n'y a jamais plus d'un thread (sauf si vous utilisez quelque chose comme " Travailleurs Web »).

Donc, si vous souhaitez utiliser Settimeout () pour améliorer les performances lors d'une tâche intensive de calcul, vous devez casser cette tâche en petits morceaux et exécuter les en commandes, les enchaînant ensemble en utilisant Settimeout () . Quelque chose comme ça fonctionne bien: xxx

Remarque:

  1. Les fonctions sont exécutées dans l'ordre. Il peut y en avoir autant que nécessaire.
  2. Lorsque la première fonction renvoie, la suivante est appelée via Settimeout () .
  3. La valeur du délai d'attente que j'ai utilisé est 1 . Ceci suffit pour causer un rendement et que le navigateur prendra le thread s'il en a besoin ou permettra à la prochaine tâche de procéder s'il y a du temps. Vous pouvez expérimenter d'autres valeurs si vous ressentez le besoin, mais généralement 1 est ce que vous voulez à ces fins.

2 commentaires

Au lieu de lutter avec un index, vous pouvez Shift Éléments hors du tableau après avoir testé sa longueur .


Oui, cela fonctionnerait aussi. Cela dépend de savoir s'il est correct d'avoir la matrice de tâches détruite dans le processus. En outre, la simple manipulation d'un indice devrait être sensiblement meilleure que l'opération de décalage (bien que certes performance ne soit probablement pas la principale préoccupation dans ce cas particulier).