Réponses:
Il est plus simple d'appeler directement la fonction directement la première fois:
foo();
setInterval(foo, delay);
Cependant, il y a de bonnes raisons d'éviter setInterval
- en particulier dans certaines circonstances, toute une série d' setInterval
événements peuvent arriver immédiatement les uns après les autres sans aucun retard. Une autre raison est que si vous voulez arrêter la boucle, vous devez appeler explicitement, clearInterval
ce qui signifie que vous devez vous souvenir du handle renvoyé par l' setInterval
appel d' origine .
Donc, une autre méthode consiste à se foo
déclencher pour les appels suivants en utilisant à la setTimeout
place:
function foo() {
// do stuff
// ...
// and schedule a repeat
setTimeout(foo, delay);
}
// start the cycle
foo();
Cela garantit qu'il y a au moins un intervalle delay
entre les appels. Cela facilite également l'annulation de la boucle si nécessaire - vous n'appelez simplement pas setTimeout
lorsque votre condition de fin de boucle est atteinte.
Mieux encore, vous pouvez envelopper tout cela dans une expression de fonction immédiatement invoquée qui crée la fonction, qui se rappelle ensuite comme ci-dessus et démarre automatiquement la boucle:
(function foo() {
...
setTimeout(foo, delay);
})();
qui définit la fonction et démarre le cycle d'un seul coup.
setTimeout
?
setInterval
événements peut arriver immédiatement les uns après les autres sans aucun retard.
setTimeout
méthode?
Je ne sais pas si je vous comprends bien, mais vous pourriez facilement faire quelque chose comme ça:
setInterval(function hello() {
console.log('world');
return hello;
}(), 5000);
Il y a évidemment un certain nombre de façons de procéder, mais c'est la façon la plus concise à laquelle je peux penser.
arguments.callee
n'est pas disponible en mode strict ES5
Je suis tombé sur cette question en raison du même problème, mais aucune des réponses n'aide si vous devez vous comporter exactement comme setInterval()
mais avec la seule différence que la fonction est appelée immédiatement au début.
Voici ma solution à ce problème:
function setIntervalImmediately(func, interval) {
func();
return setInterval(func, interval);
}
L'avantage de cette solution:
setInterval
peut facilement être adapté par substitutionclearInterval()
plus tardExemple:
// create 1 second interval with immediate execution
var myInterval = setIntervalImmediately( _ => {
console.log('hello');
}, 1000);
// clear interval after 4.5 seconds
setTimeout( _ => {
clearInterval(myInterval);
}, 4500);
Pour être effronté, si vous avez vraiment besoin d'utiliser, setInterval
vous pouvez également remplacer l'original setInterval
. Par conséquent, aucun changement de code n'est requis lors de l'ajout avant votre code existant:
var setIntervalOrig = setInterval;
setInterval = function(func, interval) {
func();
return setIntervalOrig(func, interval);
}
Pourtant, tous les avantages énumérés ci-dessus s'appliquent ici, mais aucune substitution n'est nécessaire.
setTimeout
solution car elle renvoie un setInterval
objet. Pour éviter d'appeler des fonctions qui sont peut-être plus tard dans le code et donc indéfinies à l'heure actuelle, j'encapsule le premier appel de fonction dans une setTimeout
fonction comme celle-ci: setTimeout(function(){ func();},0);
La première fonction est ensuite appelée après le cycle de traitement en cours, qui est également immédiatement , mais est plus d'erreur prouvée.
Vous pouvez encapsuler setInterval()
une fonction qui fournit ce comportement:
function instantGratification( fn, delay ) {
fn();
setInterval( fn, delay );
}
... puis utilisez-le comme ceci:
instantGratification( function() {
console.log( 'invoked' );
}, 3000);
Voici un wrapper pour le faire si vous en avez besoin:
(function() {
var originalSetInterval = window.setInterval;
window.setInterval = function(fn, delay, runImmediately) {
if(runImmediately) fn();
return originalSetInterval(fn, delay);
};
})();
Définissez le troisième argument de setInterval sur true et il s'exécutera pour la première fois immédiatement après l'appel de setInterval:
setInterval(function() { console.log("hello world"); }, 5000, true);
Ou omettez le troisième argument et il conservera son comportement d'origine:
setInterval(function() { console.log("hello world"); }, 5000);
Certains navigateurs prennent en charge des arguments supplémentaires pour setInterval que ce wrapper ne prend pas en compte; Je pense que ceux-ci sont rarement utilisés, mais gardez cela à l'esprit si vous en avez besoin.
Car quelqu'un a besoin d'amener l'extérieur this
comme s'il s'agissait d'une fonction de flèche.
(function f() {
this.emit("...");
setTimeout(f.bind(this), 1000);
}).bind(this)();
Si les déchets ci-dessus vous dérangent, vous pouvez faire une fermeture à la place.
(that => {
(function f() {
that.emit("...");
setTimeout(f, 1000);
})();
})(this);
Ou peut-être envisagez d'utiliser le @autobind
décorateur en fonction de votre code.
Je proposerai d'appeler les fonctions dans l'ordre suivant
var _timer = setInterval(foo, delay, params);
foo(params)
Vous pouvez également passer _timer
au foo, si vous le souhaitez à clearInterval(_timer)
une certaine condition
var _timer = setInterval(function() { foo(_timer, params) }, delay);
foo(_timer, params);
Voici une version simple pour les novices sans tous les ennuis. Il déclare simplement la fonction, l'appelle, puis démarre l'intervalle. C'est tout.
//Declare your function here
function My_Function(){
console.log("foo");
}
//Call the function first
My_Function();
//Set the interval
var interval = window.setInterval( My_Function, 500 );
Il existe un package npm pratique appelé firstInterval (divulgation complète, c'est le mien).
La plupart des exemples ici n'incluent pas la gestion des paramètres, et changer les comportements par défaut de setInterval
tout grand projet est mauvais. De la documentation:
Ce modèle
setInterval(callback, 1000, p1, p2);
callback(p1, p2);
est identique à
firstInterval(callback, 1000, p1, p2);
Si vous êtes de la vieille école dans le navigateur et que vous ne voulez pas de dépendance, c'est un simple copier-coller du code.
// YCombinator
function anonymous(fnc) {
return function() {
fnc.apply(fnc, arguments);
return fnc;
}
}
// Invoking the first time:
setInterval(anonymous(function() {
console.log("bar");
})(), 4000);
// Not invoking the first time:
setInterval(anonymous(function() {
console.log("foo");
}), 4000);
// Or simple:
setInterval(function() {
console.log("baz");
}, 4000);
Ok, c'est tellement complexe, alors, permettez-moi de le dire plus simplement:
function hello(status ) {
console.log('world', ++status.count);
return status;
}
setInterval(hello, 5 * 1000, hello({ count: 0 }));
Vous pouvez définir un temps de retard initial très petit (par exemple 100) et le régler sur le temps de retard souhaité dans la fonction:
var delay = 100;
function foo() {
console.log("Change initial delay-time to what you want.");
delay = 12000;
setTimeout(foo, delay);
}
Il y a un problème avec l'appel asynchrone immédiat de votre fonction, car setTimeout / setInterval standard a un délai minimal d'environ plusieurs millisecondes même si vous le définissez directement sur 0. Cela est dû à un travail spécifique au navigateur.
Un exemple de code avec un REAL zéro retard qui fonctionne dans Chrome, Safari, Opera
function setZeroTimeout(callback) {
var channel = new MessageChannel();
channel.port1.onmessage = callback;
channel.port2.postMessage('');
}
Vous pouvez trouver plus d'informations ici
Et après le premier appel manuel, vous pouvez créer un intervalle avec votre fonction.
en fait le plus rapide est de faire
interval = setInterval(myFunction(),45000)
cela appellera ma fonction, puis le fera toutes les 45 secondes, ce qui est différent de faire
interval = setInterval(myfunction, 45000)
qui ne l'appellera pas, mais le planifiera seulement
myFunction()
retourne. Au lieu de cela, modifier chaque fonction à appeler setInterval
est une meilleure approche pour boucler setInterval
une fois comme les autres réponses le proposent.
function
une fois puis de faire lesetInterval()