Timer : settimeout & setinterval améliorés

Soyez le premier à donner votre avis sur cette source.

Vue 5 724 fois - Téléchargée 321 fois

Description

Et bien, une petite source après quelques 4 mois d'absence. J'arrive ici avec une source de calibre expert, assez lourde, qui permet de rajouter quelques fonctionnalités très intéressantes aux fonctions setTimeout et setInterval. De quoi s'agit-il ?

Il n'est pas inconnu que ces fonctions, couplées à clearTimeout et clearInterval proposent des fonctions de bases, parfois trop, ce qui posent problème. Un petit exemple très connu est la difficulté de définir des arguments pour la fonction anonyme précisé et la valeur du "this".

Et bien, je règle ces problèmes, et bien d'autres encore ! Voici lesquels :

#1 : Définir les arguments de la fonction anonyme : Cela est désormais possible. Ainsi, les arguments définis dans les fonctions (à partir du trosième) seront envoyés à la fonction anonyme. Schéma :

timer.createTimeout(fonction(a,b,c){...},1000,this,a,b,c);

#2 : La valeur du "this" : Le keyword "this" peut être défini en troisième argument, comme démontré dans le schéma ci-haut

#3 : Programmation en POO qui permet d'accéder à certaines fonctions/propriétés, comme exécuter d'avance (.exec() ) ou annuler facilement (.clear() ) sans avoir besoin de connaître l'ID du timer.

#4 : Détruire TOUS les setTimeout/setInterval définis : J'ai ajouté la fonction timer.clearAll()

Et cela en modifiant presque pas la fonction originale ! Toutefois, les fonctions timer.createTimeout/timer.createInterval ont un comportement semblable à leurs équivalents :
- Défini un temps d'exécution en millisecondes
- Possibilité d'exécuter du texte ou une fonction anonyme

Le code est très difficile, je n'ai pas encore ajouté de commentaires, je le ferai prochainement. S'il y a problèmes avec certaines parties, merci de me faire signe.

Pour voir le code en action, ainsi qu'une documentation mêlée à une explication, téléchargez le ZIP !

TIMER.JS Version 1.2

SOURCE ORIGINALE (qui ne lui ressemble plus) : Inspiré de http://arguments.callee.info/2008/11/10/passing-arguments-to-settimeout-and-setinterval/ (sans espaces, s'il y a espaces)

NOTES PAR RAPPORT À LA VERSION 1.1.2 : Merci de revoir la documentation, puisque la structure en POO est complètement différente. Il n'est plus possible de connaître le nombre de Timers définis.

Source / Exemple :


/*------------------

| TIMER API |

JDMCREATOR, 2011 VERSION 1.2 CODE START HERE http://www.javascriptfr.com/code.aspx?ID=53911 ------------------*/(function (f) { // f = fonctions qui remplaceront les setTimeout/setInterval // Définition du timer window.timer = { // key = clés des différents Timers key: {}, // Version version: '1.2', // Build : Version en nombre. build: 120, // length = nombre de timers length: 0, // _fn = Fonction temporaire permettant la construction de Timer __fn: function (f, wt) { // f = Fonction setTimeout/setInterval // wt = Nombre. 1 = Timeout, 2 = Interval return function (fn, time, cntx) { // Fonction pour créer un Timer. Fn = fonction à exécuter. time = Temps avant l'exécution. cntx = contexte; cntx = cntx || window; // Définit le contexte (cntx); var a = [].slice.call(arguments, 3); // a = Array d'arguments à passer // Si fn est une String, on l'envoie à la fonction Timer, if (fn.toString() === fn) { var t = f(function () { eval.call(cntx, fn); }, time); // Sinon, on exécutera la fonction directement, à l'aide de 'apply' } else { var t = f(function () { fn.apply(cntx, a); }, time); } // Retourne un objet. return this.convert([fn, a, wt, time], t, cntx); } }, // On supprime tous les Timers clearAll: function () { var k = this.key; for (var i in k) { var l = k[i]; if (!isNaN(i)) { if (l[2] == 1) { clearTimeout(i); } else { clearInterval(i); } } } }, // Créer un objet à partir d'un ID convert: function (k, id, cn) { // Si k est un ID, on crée if (!isNaN(parseInt(k))) { id = k; var k = this.key[k]; if (!k) { return false } } // Création de l'objet return { // type. Nombre. 1 = timeout, 2 = interval type: k[2], // source (fonction/texte à exécuter) source: k[0], // Temps time: k[3], // Contexte (si créé à partir des fonctions bruts, ce sera window) context: cn || window, // Liste des arguments args: k[1], // ID id: id, // Exécute d'avance le timer. Si argument à 'true', on ne supprimera pas le timer exec: function (keep) { var c = this.context; var s = this.source; if (s.toString() !== s) { s.apply(c, this.args); } else { eval.call(c, s); } if (!keep) { this.clear(); } }, // Supprimer le timer clear: function () { wt = this.type; if (wt == 1) { clearTimeout(id); } else if (wt == 2) { clearInterval(id); } } }; } }; // Création des fonctions createTimeout et createInterval timer.createTimeout = timer.__fn(setTimeout,1); timer.createInterval = timer.__fn(setInterval,2); // Supprime la fonction temporaire __fn); delete timer.__fn; // On remplace les fonctions bruts. window.setTimeout = f(window.setTimeout, 1); window.setInterval = f(window.setInterval, 2) })(function (f, wt) { // a = arguments var a = [].slice.call(arguments, 2); return function (c, t) { // On crée la fonction à envoyer à la fonction brute. var j = f(c, t); window.timer.length++; window.timer.key[j] = [c, a, wt, t]; return j; } });

Conclusion :


DOCUMENTATION :

Merci de voir le fichier 'demo.html' ! La version commenté du script n'est disponible qu'ici. Elle n'est fournie dans le ZIP.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

cs_Kimjoa
Messages postés
264
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
19 septembre 2014
-
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 .
jdmcreator
Messages postés
656
Date d'inscription
samedi 30 décembre 2000
Statut
Membre
Dernière intervention
20 juillet 2012
3 -
@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
264
Date d'inscription
vendredi 6 mai 2005
Statut
Membre
Dernière intervention
19 septembre 2014
-
"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
656
Date d'inscription
samedi 30 décembre 2000
Statut
Membre
Dernière intervention
20 juillet 2012
3 -
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_alain17610
Messages postés
15
Date d'inscription
samedi 22 novembre 2008
Statut
Membre
Dernière intervention
21 avril 2016
-
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é ?

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.