J'ai du code JavaScript qui ressemble à:
function statechangedPostQuestion()
{
//alert("statechangedPostQuestion");
if (xmlhttp.readyState==4)
{
var topicId = xmlhttp.responseText;
setTimeout("postinsql(topicId)",4000);
}
}
function postinsql(topicId)
{
//alert(topicId);
}
J'obtiens une erreur topicId
non définie Tout fonctionnait avant d'utiliser la setTimeout()
fonction.
Je veux que ma postinsql(topicId)
fonction soit appelée après un certain temps. Que devrais-je faire?
javascript
parameters
callback
settimeout
Zeeshan Rang
la source
la source
Réponses:
Vous devez alimenter une fonction anonyme en paramètre au lieu d'une chaîne, cette dernière méthode ne devrait même pas fonctionner selon la spécification ECMAScript, mais les navigateurs sont tout simplement indulgents. C'est la bonne solution, ne comptez jamais sur le passage d'une chaîne en tant que «fonction» lorsque vous utilisez
setTimeout()
ousetInterval()
, c'est plus lent car il doit être évalué et ce n'est tout simplement pas correct.MISE À JOUR:
Comme Hobblin l'a dit dans ses commentaires à la question, vous pouvez maintenant passer des arguments à la fonction à l'intérieur de setTimeout en utilisant
Function.prototype.bind()
.Exemple:
la source
window.setTimeout
est une méthode DOM, et en tant que telle n'est pas définie par la spécification ECMAScript. Passer une chaîne a toujours fonctionné dans les navigateurs, et est un standard de facto - en fait, la possibilité de passer un objet fonction a été ajoutée plus tard, avec JavaScript 1.2 - cela fait explicitement partie du projet de spécification HTML5 ( whatwg.org/specs/web -apps / travaux en cours / multipage /… ). Cependant, l'utilisation d'une chaîne au lieu d'un objet fonction est généralement considérée comme un style médiocre car il s'agit essentiellement d'une forme de retardeval()
.Dans les navigateurs modernes, le "setTimeout" reçoit un troisième paramètre qui est envoyé en paramètre à la fonction interne à la fin du temporisateur.
Exemple:
Plus de détails:
la source
Après avoir fait quelques recherches et tests, la seule implémentation correcte est:
setTimeout transmettra tous les paramètres supplémentaires à votre fonction afin qu'ils puissent y être traités.
La fonction anonyme peut fonctionner pour des choses très basiques, mais dans l'instance d'un objet où vous devez utiliser "ceci", il n'y a aucun moyen de le faire fonctionner. Toute fonction anonyme changera «ceci» pour pointer vers la fenêtre, vous perdrez donc la référence de votre objet.
la source
var that = this; setTimeout( function() { that.foo(); }, 1000);
Il s'agit d'une très vieille question avec une réponse déjà "correcte" mais j'ai pensé mentionner une autre approche que personne n'a mentionnée ici. Ceci est copié et collé à partir de l'excellente bibliothèque de soulignements :
Vous pouvez passer autant d'arguments que vous le souhaitez à la fonction appelée par setTimeout et en tant que bonus supplémentaire (enfin, généralement un bonus), la valeur des arguments passés à votre fonction est gelée lorsque vous appelez setTimeout, donc s'ils changent de valeur à un moment donné entre le moment où setTimeout () est appelé et le moment où il expire, eh bien ... ce n'est plus si horriblement frustrant :)
Voici un violon où vous pouvez voir ce que je veux dire.
la source
J'ai récemment rencontré la situation unique d'avoir besoin d'utiliser un
setTimeout
dans une boucle . Comprendre cela peut vous aider à comprendre comment transmettre des paramètres àsetTimeout
.Méthode 1
Utilisez
forEach
etObject.keys
, selon la suggestion de Sukima :Je recommande cette méthode.
Méthode 2
Utilisation
bind
:JSFiddle: http://jsfiddle.net/MsBkW/
Méthode 3
Ou si vous ne pouvez pas utiliser
forEach
oubind
, utilisez un IIFE :Méthode 4
Mais si vous ne vous souciez pas d'IE <10, vous pouvez utiliser la suggestion de Fabio :
Méthode 5 (ES6)
Utilisez une variable de portée de bloc:
Bien que je recommanderais toujours d'utiliser
Object.keys
avecforEach
dans ES6.la source
.bind
ne fonctionnera pas pour IE8 et les versions antérieures [ref: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ]. J'ai fini par utiliser la solution de Schien: stackoverflow.com/a/21213723/1876899bind
alors vous aussi dans un environnement qui offreObject.keys
etforEach
. Vous pouvez perdre la boucle for et obtenir une fonction "libre" (comme dans deux oiseaux avec une pierre libre et non sans ressources) dans le processus.async
bibliothèque ( github.com/caolan/async ). Nous l'utilisons largement dans les voiles et avons eu d'excellents résultats au cours des 2 dernières années. Elle fournit des méthodes à la fois parallèle et en série pour asynchroneforEach
,map
,reduce
, etc.Hobblin a déjà commenté cela sur la question, mais cela devrait vraiment être une réponse!
L'utilisation
Function.prototype.bind()
est le moyen le plus propre et le plus flexible de le faire (avec en prime la possibilité de définir lethis
contexte):Pour plus d'informations, consultez ces liens MDN:
https://developer.mozilla.org/en/docs/DOM/window.setTimeout#highlighter_547041 https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/Function / bind # With_setTimeout
la source
setTimeout(postinsql.bind(this, topicId), 4000);
bind
. Cela donne vraiment du code lisible.Certaines réponses sont correctes mais alambiquées.
Je réponds à cela encore 4 ans plus tard, car je rencontre toujours du code trop complexe pour résoudre exactement cette question. Il existe une solution élégante.
Tout d'abord, ne passez pas une chaîne comme premier paramètre lorsque vous appelez setTimeout car cela invoque effectivement un appel à la fonction lente "eval".
Alors, comment passer un paramètre à une fonction de temporisation? En utilisant la fermeture:
Certains ont suggéré d'utiliser une fonction anonyme lors de l'appel de la fonction timeout:
La syntaxe fonctionne. Mais au moment où le settopic est appelé, c'est-à-dire 4 secondes plus tard, l'objet XHR peut ne pas être le même. Il est donc important de pré-lier les variables .
la source
Ma réponse:
Explication:
OU
Cela se traduit essentiellement par:
EDIT: J'ai vu la même réponse, alors regardez la sienne. Mais je n'ai pas volé sa réponse! J'ai juste oublié de regarder. Lisez l'explication et voyez si cela aide à comprendre le code.
la source
topicId
sont modifiées, la valeur dans le délai d'attente change également. Un clone l'a corrigéRemplacer
avec
ou mieux encore, remplacez l'expression de chaîne par une fonction anonyme
ÉDITER:
Le commentaire de Brownstone est incorrect, cela fonctionnera comme prévu, comme démontré en l'exécutant dans la console Firebug
Notez que je suis d'accord avec les autres sur le fait que vous devez éviter de passer une chaîne à
setTimeout
car cela appelleraeval()
la chaîne et passera à la place une fonction.la source
Vous pouvez passer le paramètre à la fonction de rappel setTimeout en tant que:
setTimeout (fonction, millisecondes, param1, param2, ...)
par exemple.
la source
setTimeout( (p) => { console.log(p); }, 1000, "hi" );
La solution de navigateur croisé la plus simple pour prendre en charge les paramètres dans setTimeout:
Si cela ne vous dérange pas de ne pas prendre en charge IE 9 et inférieur:
https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
la source
Je sais que cela fait 10 ans depuis que cette question a été posée, mais quand même, si vous avez fait défiler jusqu'à ici, je suppose que vous êtes toujours confronté à un problème. La solution de Meder Omuraliev est la plus simple et peut aider la plupart d'entre nous, mais pour ceux qui ne veulent pas de liaison, la voici:
la source
Je sais que c'est vieux mais je voulais y ajouter ma saveur (préférée).
Je pense qu'un moyen assez lisible pour y parvenir est de passer le
topicId
à une fonction, qui à son tour utilise l'argument pour référencer l'ID du sujet en interne. Cette valeur ne changera pas même sitopicId
à l'extérieur elle sera modifiée peu de temps après.ou court:
la source
La réponse de David Meister semble prendre en compte les paramètres qui peuvent changer immédiatement après l'appel à setTimeout () mais avant l'appel de la fonction anonyme. Mais c'est trop lourd et pas très évident. J'ai découvert une manière élégante de faire à peu près la même chose en utilisant IIFE (expression de fonction immédiatement invikée).
Dans l'exemple ci-dessous, la
currentList
variable est passée à l'IIFE, qui l'enregistre dans sa fermeture, jusqu'à ce que la fonction retardée soit invoquée. Même si la variablecurrentList
change immédiatement après le code affiché, lesetInterval()
fera la bonne chose.Sans cette technique IIFE, la
setTimeout()
fonction sera certainement appelée pour chaqueh2
élément du DOM, mais tous ces appels ne verront que la valeur textuelle du dernierh2
élément.la source
En général, si vous devez passer une fonction en tant que rappel avec des paramètres spécifiques, vous pouvez utiliser des fonctions d'ordre supérieur. C'est assez élégant avec ES6:
Ou si
someFunction
c'est la première commande:la source
Notez que la raison pour laquelle topicId n'était "pas défini" par le message d'erreur est qu'il existait en tant que variable locale lorsque setTimeout a été exécuté, mais pas lorsque l'appel retardé à postinsql s'est produit. Il est particulièrement important de faire attention à la durée de vie variable, en particulier lorsque vous essayez quelque chose comme passer "ceci" comme référence d'objet.
J'ai entendu dire que vous pouvez passer topicId comme troisième paramètre à la fonction setTimeout. Peu de détails sont donnés mais j'ai suffisamment d'informations pour le faire fonctionner, et c'est réussi dans Safari. Cependant, je ne sais pas ce qu'ils signifient à propos de "l'erreur de la milliseconde". Vérifiez le ici:
http://www.howtocreate.co.uk/tutorials/javascript/timers
la source
Comment j'ai résolu cette étape?
juste comme ça :
setTimeout attend une référence à une fonction, donc je l'ai créée dans une fermeture, qui interprète mes données et retourne une fonction avec une bonne instance de mes données!
Vous pouvez peut-être améliorer cette partie:
Je l'ai testé sur Chrome, Firefox et IE et il s'exécute bien, je ne connais pas les performances mais j'en avais besoin pour fonctionner.
un exemple de test:
Vous pouvez peut-être modifier la signature pour la rendre plus conforme:
Et enfin pour répondre à la question d'origine:
J'espère que cela peut aider!
ps: désolé mais l'anglais ce n'est pas ma langue maternelle!
la source
cela fonctionne dans tous les navigateurs (IE est une excentrique)
la source
si vous voulez passer une variable en paramètre, essayez ceci
si l'exigence est la fonction et var comme parmas alors essayez ceci
si l'exigence n'est que des variables en tant que paramètres, essayez ceci
Vous pouvez essayer cela avec ES5 et ES6
la source
Vous pouvez essayer la fonctionnalité par défaut de 'apply ()' quelque chose comme ça, vous pouvez passer plus de nombre d'arguments que votre exigence dans le tableau
la source
setTimeout fait partie du DOM défini par WHAT WG.
https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html
La méthode que vous souhaitez est: -
Apparemment, des arguments supplémentaires sont pris en charge dans IE10. Alternativement, vous pouvez utiliser
setTimeout(postinsql.bind(null, topicId), 4000);
, mais passer des arguments supplémentaires est plus simple, et c'est préférable.Factoid historique: À l'époque de VBScript, en JScript, le troisième paramètre de setTimeout était le langage, sous forme de chaîne, par défaut "JScript" mais avec l'option d'utiliser "VBScript". https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa741500(v%3Dvs.85)
la source
@Jiri Vetyska merci pour le message, mais il y a quelque chose qui ne va pas dans votre exemple. J'avais besoin de passer la cible qui est en vol stationnaire (ceci) à une fonction de temporisation et j'ai essayé votre approche. Testé dans IE9 - ne fonctionne pas. J'ai également fait quelques recherches et il semble que, comme indiqué ici, le troisième paramètre soit le langage de script utilisé. Aucune mention de paramètres supplémentaires.
J'ai donc suivi la réponse de @ meder et résolu mon problème avec ce code:
J'espère que c'est utile pour quelqu'un d'autre.
la source
Comme il y a un problème avec le troisième paramètre optonal dans IE et l'utilisation de fermetures nous empêche de changer les variables (dans une boucle par exemple) et d'atteindre toujours le résultat souhaité, je suggère la solution suivante.
Nous pouvons essayer d'utiliser la récursion comme ceci:
Nous devons nous assurer que rien d'autre ne change ces variables et que nous écrivons une condition de récursivité appropriée pour éviter une récursion infinie.
la source
// Ce sont trois réponses très simples et concises:
la source
Répondre à la question mais par une simple fonction d'addition avec 2 arguments.
la source
Vous devez supprimer les guillemets de votre
setTimeOut
appel de fonction comme ceci:la source
Je pense que tu veux:
la source
JSON.stringify
pour les objets et les tableaux réguliers, puis utilisez l'JSON.parse
intérieur de la fonction. Cependant, tout comportement sera perdu si l'objet a des méthodes.// Ce sont trois réponses très simples et concises:
la source