TIMER : SETTIMEOUT & SETINTERVAL AMÉLIORÉS

cs_Kimjoa Messages postés 262 Date d'inscription vendredi 6 mai 2005 Statut Membre Dernière intervention 19 septembre 2014 - 30 déc. 2011 à 05:05
jdmcreator Messages postés 647 Date d'inscription samedi 30 décembre 2000 Statut Membre Dernière intervention 20 juillet 2012 - 11 févr. 2012 à 17:05
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/53911-timer-settimeout-setinterval-ameliores

jdmcreator Messages postés 647 Date d'inscription samedi 30 décembre 2000 Statut Membre Dernière intervention 20 juillet 2012 7
11 févr. 2012 à 17:05
Voilà pour la version commentée !
jdmcreator Messages postés 647 Date d'inscription samedi 30 décembre 2000 Statut Membre Dernière intervention 20 juillet 2012 7
6 janv. 2012 à 17:10
Bonjour Kimjoa, je te répond rapidement de mon téléphone :

Pour ton idée de créer une classe groupé, je pourrais ajouter la possibilité de définir un 'name' au timex et de supprimer tous les timex ayant ce nom. Ce serait la méthode la plus simple.

Pour eval, je ne comprends pas pourquoi on ne pourrait pas choisir un autre contexte :S Est-ce parce que cela n'a aucun résultat ?

Quant à la partie que tu ne comprends pas, si tu regardes à la fin de mon fichier demo.html, j'explique qu'il est possible de convertir un Timex créé grâce aux méthodes classiques setTimeout/setInterval en passant l'ID du timex à la fonction timer.convert(ID) . Cette fonction a donc 2 utilités : une que le codeur ne verra jamais (celle avec les Array, qui me permet de réduire mon code) et celle décrite dans la documentation.

Et merci pour la dernière remarque :) C'est impressionnant tout ce que Javascript nous permet. Et c'est pour cette raison que je vais commenter la source le plus tôt possible !

JDMCreator
cs_Kimjoa Messages postés 262 Date d'inscription vendredi 6 mai 2005 Statut Membre Dernière intervention 19 septembre 2014
6 janv. 2012 à 16:33
Salut jdmcreator!

Ton code me plais déjà mieux ;).
L'idée de renvoyer un objet lors de la création d'un timex est plutot bien vue.

En faite quand je t'ai dit de préférer une approche POO, je pensais plus à quelque chose du genre :

var monGroupeDeTimer = new Timers();
var monTimer = monGroupeDeTimer.createTimeout(...);
var monInterval = monGroupeDeTimer.createInterval(...);
...
monGroupeDeTimer.clearAll();

Avec aussi, une méthode de classe clearAll qui fait la même chose mais pour tout les timer , et non un groupe instancié.
Mais bon c'est un peux chipotter, d'autant plus qu'il aurait été nécessaire de répéter certaines autre méthodes d'instance, pour permettre de ne pas être obliger l'instanciation d'un groupe.

Je comprends presque tout ton code sauf une partie :
if (!isNaN(parseInt(k))) {id k;var k this.key[k];if (!k) {return false}}

k est sencé etre un tableau .... pourquoi le transformer en nombre et tester isNaN ?

Sinon, du coté du eval.
f(function () {eval.call(cntx, fn);}, time);
Ca me semble une érreur.
eval doit toujours être appellé au niveau global. Le contexte de toute facon sera évalué en même temps.
donc eval.call(window, fn)

J'ai pas d'autre remarque sinon. Enfin si peux être :).
C'est un code compliqué quand même , dans le sens ou c'est une succession de lambda comme on dit ...
Des fonctions passé en arguments qui retourne des fonctions etc... Il est pas à la porté du premier javascripteur !
C'est un beau tour de force de ce que permet javascript , son coté dynamique et fonctionnelle

Tchuss!
jdmcreator Messages postés 647 Date d'inscription samedi 30 décembre 2000 Statut Membre Dernière intervention 20 juillet 2012 7
6 janv. 2012 à 04:16
Bonjour Kimjoa,

J'ai posté la version 1.2 . Je n'ai pas encore commenté, mais si tu pourrais regarder tout cela (le fichier demo.html explique assez bien) et me donner tes commentaires, ce serait gentil =) Malheureusement, j'ai encore modifié les fonctions setTimeout/setInterval, mais dans une moins grande ampleur que dans les versions précédentes. J'essaierai de réduire encore plus les impacts dans les prochaines mises à jour. Le code contient encore des bugs que je m'efforce à régler, mais comme je ne serai pas là en fin de semaine, la version 1.2.1 et la version commenté devra encore attendre !

Merci,

JDMCreator
jdmcreator Messages postés 647 Date d'inscription samedi 30 décembre 2000 Statut Membre Dernière intervention 20 juillet 2012 7
3 janv. 2012 à 18:03
@Kimjoa :

Le problème, c'est que si ne redéfinis pas les méthodes Timex, je ne peux pas lister les Timers définis (pour pouvoir les supprimer via clearAll() )
cs_Kimjoa Messages postés 262 Date d'inscription vendredi 6 mai 2005 Statut Membre Dernière intervention 19 septembre 2014
3 janv. 2012 à 15:08
ps : "Et pour le setImmediate, ..."
Il fournit des testes dans sa source, oups !
cs_Kimjoa Messages postés 262 Date d'inscription vendredi 6 mai 2005 Statut Membre Dernière intervention 19 septembre 2014
3 janv. 2012 à 15:00
@jdmcreator

"Dans quel cas, par exemple ?"

Dans un context POO. Si j'ai un objet d'une classe Effet , j'aimerais bien exécuter le script avec le this adéquat. Même on peux toujours passer une référence en arguments.

"Et pour le setImmediate, regarde ceci https://github.com/NobleJS/setImmediate et dis-moi ce que tu en penses !"

Ca m'a l'air très bien codé, et pour être sincère je comprends pas tout du code , même en mettant documenté. Il semble utilisé des techniques bien spécifique à chaque navigateur. Une batterie de teste devrait être nécessaire pour être sur à 100% de la compatibilité de cette source, hors, il n'en donne aucun. C'est dommage, perso, je m'y risquerait pas.

"@Kimjoa : Après rapide réflexion, si je cessais de modifier la fonction native, on perdrait un aspect important de la source ...."

Je pense que tu peux faire les deux. Redéfinir les setTimex et clearTimex, et une méthode de classe clearAll, pour tout effacer, en plus d'une méthode de prototype clearAll. Mais bon , perso, je redéfinirai pas les fonctions native ...

-30 degrés ... faut si préparé ! bon courage lol !
jdmcreator Messages postés 647 Date d'inscription samedi 30 décembre 2000 Statut Membre Dernière intervention 20 juillet 2012 7
2 janv. 2012 à 23:53
J'ai mis à jour le code avec quelques petites modifications (V 1.1.2) :

1 - J'ai couper dans le code en utilisant la même technique setTimeout/setInterval pour clearTimeout/clearInterval
2 - Changer rapidement le keyword "native". Honte à moi.

@Kimjoa : Après rapide réflexion, si je cessais de modifier la fonction native, on perdrait un aspect important de la source : pouvoir avoir un contrôle sur TOUS les setTimeout définis, et non pas sur ceux définis par l'API uniquement. Par contre, je pourrais tenter une fusion des deux approches. C'est d'ailleurs ce que je vais faire (je réfléchis souvent en écrivant xD)
jdmcreator Messages postés 647 Date d'inscription samedi 30 décembre 2000 Statut Membre Dernière intervention 20 juillet 2012 7
2 janv. 2012 à 23:28
@Alain

En fait, c'est complètement mon erreur, cela aurait du être http://www.espacejavascript.com/exemple.php?id=224 :S Néanmoins, j'ai mis à jour le script et inclus un ZIP, tu peux donc le télécharger pour voir l'exemple. C'est plus simple ainsi. Et merci pour la note !

@Kimjoa :

Je vais répondre à tous tes points xD

"-Ré-implémenter des fonctions native est une mauvaise pratique. Même si elle ne perturbe pas dans ton cas leurs fonctionnement normale. Une classe , aurait été meilleur une option ?"

Sûrement. Cela donne un code moins impressionnant, mais je crois que ce serait le meilleur.

"Une vision POO aurait été préférable je pense. Notamment en ce qui concerne la fonction clearAll. En opérant ainsi, seule un groupe de timer bien de ciblé aurait été effacé. Cela aurait pu apporter plus de souplesse..."

En le couplant avec le premier point, cela pourrait donner quelque chose d'un peu plus userfriendly que les ID de timers

"choisir par défaut window comme contexte d'exécution n'est pas forcement ce que l'utilisateur souhaiterait. "

Dans quel cas, par exemple ?

"native est un mot réservé , mieux vaut l'éviter"

C'est un bon point !

Et pour le setImmediate, regarde ceci https://github.com/NobleJS/setImmediate et dis-moi ce que tu en penses !

Et finalement, ici, il fait -6 :) Et il fait chaud ! J'ai plus ou moins hâte aux -30. Par contre, il y a 1 mètre de neige !
cs_Kimjoa Messages postés 262 Date d'inscription vendredi 6 mai 2005 Statut Membre Dernière intervention 19 septembre 2014
2 janv. 2012 à 17:46
@jdmcreator

Bonne année à toi aussi ;)

Alors, je enfin compris ton code !!
Il est assez complexe en effet. J'ai quelques petite remarque à faire tout de même.

-Ré-implémenter des fonctions native est une mauvaise pratique. Même si elle ne perturbe pas dans ton cas leurs fonctionnement normale. Une classe , aurait été meilleur une option ?

-Une vision POO aurait été préférable je pense. Notamment en ce qui concerne la fonction clearAll. En opérant ainsi, seule un groupe de timer bien de ciblé aurait été effacé. Cela aurait pu apporter plus de souplesse...

-la fonction execTimer devrait avoir 2 comportements distinct.Dans ton exemple, l'intervalle n'est pas repoussé une fois execTimer est invoqué. C'est pas forcement le comportement que l'utilisateur voudrait. Un troisième arguments serait nécessaire non?

-choisir par défaut window comme contexte d’exécution n'est pas forcement ce que l'utilisateur souhaiterait. Le 3 ème arguments devrait être le contexte. Bind qui permet de faire ça, et encore une fois, cette fonction est normalisé, donc à utilisé. Une implémentation de mozilla ce trouve ici -> https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

-native est un mot réservé , mieux vaut l'éviter.

Sinon "C'était à utiliser à intervalles irréguliers (un objet ralentissant sa course). Il était impossible d'utiliser un setInterval."

Je vois pas pourquoi. Une variable sur la vitesse de l'effet aurait pu suffire

"Oui, cela semble assez complexe :/ Il faudrait me donner une utilisation pratique pour que je puisse comprendre la situation..."

Alors pour ce qu'il s'agit d’exécution en parallèle, imagine qu'il faille parser dans ton application en gros fichier xml... Le temps que l’interpréteur javascript fasse son travaille, toute l'interface utilisateur comportent du js est gelé. D'ou la nécessité d'essayer d'alterner les deux traitements, et setImmediate permet de faire cette alternance plus aisément que setTimeout pour le moteur js. Il existe aussi les WebWorker pour faire des threads, mais ceux ci sont assez limité, n'ayant pas d'accès a l'objet global window, et ne fonctionnant que via des callback et du JSON.

"Finalement, j'habite au Canada"

J'ai froid pour toi lol ! Ici vers paris il fait 15 degrés , et ça dure depuis tout l’automne du jamais vue !!
A+
cs_alain17610 Messages postés 17 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 13 janvier 2021
2 janv. 2012 à 15:08
Bonjour jdmcreator.

Les "timers" m'intéressant, j'ai fait un copier/coller avec cette adresse :
http://www.editeurjavascript.com/exemple.php?id=224.

Eh bien(non "Et bien")je suis tombé sur une page "404" indiquant ce qui suit :
"La page que vous essayez d'afficher n'existe pas
Le site vient de subir de profonde modification. Il est donc tout a fait normal que vous tombiez sur cette page d'erreur." [...]

Ai-je commis une erreur ou alors le lien indiqué a t-il changé ?
jdmcreator Messages postés 647 Date d'inscription samedi 30 décembre 2000 Statut Membre Dernière intervention 20 juillet 2012 7
31 déc. 2011 à 21:35
Voilà j'ai commenté et j'ai un peu amélioré la vitesse =)

@Kimjoa :

"Les timers utilisent beaucoup de ressources, il faut en limiter l'usage."

C'était à utiliser à intervalles irréguliers (un objet ralentissant sa course). Il était impossible d'utiliser un setInterval.

"Et bien, bind permet d'assigner des paramètres et un contexte d'exécution, à une fonction, avant sont exécution. Puisque c'est standardisé, son extension dans le prototype de Function ne pause plus de problème ... "

Je ne vois pas vraiment où je pourrais l'utiliser et où ça pourrait vraiment apporter quelque chose...

"En faite setTimeout devrait pouvoir se suffire à lui même pour simuler de l'exécution en parallèle. Enfin c'est un sujet pas mal complexe [...]"

Oui, cela semble assez complexe :/ Il faudrait me donner une utilisation pratique pour que je puisse comprendre la situation...

Je te laisse regarder le code commenté et tu me diras si tu comprends mieux, sinon j'essaierai de mieux m'exprimer pour mieux t'expliquer.

Finalement, j'habite au Canada, ce n'est donc pas encore le soir (15:34), mais bon Réveillon et bonne nouvelle année :)
cs_Kimjoa Messages postés 262 Date d'inscription vendredi 6 mai 2005 Statut Membre Dernière intervention 19 septembre 2014
31 déc. 2011 à 01:23
"Comprends-tu plus l'intérêt de ce que je propose ?"
Toujours pas :(

"On plaçait tous les setTimeout de l'effet dans l'objet"

Les timers utilisent beaucoup de ressources, il faut en limiter l'usage.
Pour de l'animation, un seul est suffisant, pour tout les objets et effets. De plus un seule intervalle permet une bien meilleur synchronisation. J'ai déjà rencontré ce problème et utilisé partiellement cette technique ici http://www.javascriptfr.com/codes/DYNAMIQUE-JS-FAIRE-JOLIE-ANIMATION_47712.aspx

"Je ne comprends pas vraiment ce que tu veux dire par là, mais "bind" n'est pas compatible avec les vieux navigateurs."

Et bien, bind permet d'assigner des paramètres et un contexte d’exécution, à une fonction, avant sont exécution. Puisque c'est standardisé, son extension dans le prototype de Function ne pause plus de problème ...

"C'est intéressant. Je vais m'informer. Je sais qu'il existe setImmediate() dans IE10, je ne sais pas si cela a un lien avec ce que tu dis, mais je vais faire des recherches."

En faite setTimeout devrait pouvoir se suffire à lui même pour simuler de l'exécution en parallèle. Enfin c'est un sujet pas mal complexe ...Par exemple un setTimeout(fn, 0); va exécute la fonction une fois que le moteur js aura un peux de temps. En multipliant les appels de setTimeout à 0 milliseconde , on peux simuler du parallélisme ... Enfin je suis pas expert sur le sujet ;)
setImmediate() permet de contourner un problème lié à la fréquence du traitement d'opération différé. Si j'ai bien comprit la fréquence en HTML4 est de 1/64 de seconde. C'est à dire que l'intervalle minimum est de 1/64 de seconde pour les fonctions setTimex. setImmediate permet en faite d'exécuté un , ou plusieurs script différé des que le moteur le moteur js a finit ses traitements, et donc de ne plus d'attendre un minimum de 1/64 de seconde ...

J'ai beau relire le code , je voit pas ! Ca à l'air intéressant pourtant , mais sans commentaires, c'est un peu l'angoisse lol
jdmcreator Messages postés 647 Date d'inscription samedi 30 décembre 2000 Statut Membre Dernière intervention 20 juillet 2012 7
30 déc. 2011 à 18:37
@Kimjoa :

"j'ai rien comprit. Il s'agit de faire quoi au final?"

Un programme qui pallie les différents programmes de setTimeout, que j'ai listé au début. Ce qui m'a amené à créer ceci, c'est après la création d'un module d'effet pour un script. Elle fonctionnait de cette façon :

1- On créait un objet Effet
2- On plaçait tous les setTimeout de l'effet dans l'objet
3- Il était possible d'arrêter l'effet en faisant un "clear" sur tous les setTimeout.
4- Il était possible de finaliser un effet en annulant tous les setTimeout puis d'excéuter en avance le dernier.

Cela ne se fait pas en ne modifiant pas la fonction de base, en plus que j'avais besoin de passé des arguments à la fonction anonyme.

Comprends-tu plus l'intérêt de ce que je propose ?

"L'évaluation d'une chaîne caractère comme arguments d'un intervalle est depuis longtemps déprécié"

Absolument. Mais tant qu'à modifié une fonction du système, il faut s'assurer qu'elle reste compatible avec les anciens scripts

"Le contexte d'exécution d'une fonction passé en arguments à été standardisé via la fonction bind de l'objet Function (ecmascript 5). bind permet aussi de faire du "curring" , permettant d'assigner les arguments à passer à l'appel de la fonction passé en paramètre.. "

Je ne comprends pas vraiment ce que tu veux dire par là, mais "bind" n'est pas compatible avec les vieux navigateurs.

"Il aurait été plus intéressant , selon moi, d'essayer d'introduire une notion de thread, pour des exécutions lourdes pouvant freezer l'ui. Une alternative aux webworker ...."

C'est intéressant. Je vais m'informer. Je sais qu'il existe setImmediate() dans IE10, je ne sais pas si cela a un lien avec ce que tu dis, mais je vais faire des recherches.

"Enfin une explication plus claire serait la bien venue, le code étant assez indigeste , même pour un expert !!! lol"

Je vais commenter bientôt ;)

"ps : eval isn't evil !! ca permet de faire beaucoup de chose, de la compilation à la volé , hmmmm même pour du code interprété ;) .... c'est la mauvaise connaissance des bases du javascript qui on fait cette si mauvaise réputation à eval . "

Eval n'est pas evil, mais c'est pourtant ce qu'on apprend aux débutants sur les sites d'apprentissage du Javascript, puisque souvent les débutants l'utilisent de mauvaises façons. Habituellement, on peut remplacer eval() par setTimeout("",0), mais comme c'est exactement la fonction que je modifie, c'est peu pratique xD
cs_Kimjoa Messages postés 262 Date d'inscription vendredi 6 mai 2005 Statut Membre Dernière intervention 19 septembre 2014
30 déc. 2011 à 05:05
j'ai rien comprit. Il s'agit de faire quoi au final?
L'évaluation d'une chaîne caractère comme arguments d'un intervalle est depuis longtemps déprécié.
Le contexte d’exécution d'une fonction passé en arguments à été standardisé via la fonction bind de l'objet Function (ecmascript 5). bind permet aussi de faire du "curring" , permettant d'assigner les arguments à passer à l'appel de la fonction passé en paramètre..
Il aurait été plus intéressant , selon moi, d’essayer d'introduire une notion de thread, pour des exécutions lourdes pouvant freezer l'ui. Une alternative aux webworker ....
Enfin une explication plus claire serait la bien venue, le code étant assez indigeste , même pour un expert !!! lol

ps : eval isn't evil !! ca permet de faire beaucoup de chose, de la compilation à la volé , hmmmm même pour du code interprété ;) .... c'est la mauvaise connaissance des bases du javascript qui on fait cette si mauvaise réputation à eval .
Rejoignez-nous