Comment puis-je passer un paramètre à un rappel setTimeout ()?

827

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 topicIdnon 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?

Zeeshan Rang
la source
75
ça fait un peu mal de commenter un sujet aussi ancien mais je dois juste proposer une troisième version (qui à mon avis est beaucoup plus propre): setTimeout (postinsql.bind (null, topicId), 4000)
Hobblin
14
@Hobblin: pourquoi ça ferait mal de remettre les pendules à l'heure? Cela ne ferait-il pas plus de mal aux autres de se poser sur cette question populaire et de voir l'ancien style d'appel découragé?
Dan Dascalescu
2
tout est clair ici: w3schools.com/jsref/met_win_settimeout.asp
Vladislav
@dbliss Ma suggestion a déjà été mentionnée dans plusieurs des réponses et ajoutée comme réponse ici: stackoverflow.com/a/15620038/287130 Mais je suis content que ma suggestion soit appréciée;)
Hobblin
@Hobblin ah, merci beaucoup de l'avoir signalé. j'avais parcouru la recherche d'une réponse postée par vous et je l'ai manquée.
dbliss

Réponses:

1123
setTimeout(function() {
    postinsql(topicId);
}, 4000)

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()ou setInterval(), 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:

setTimeout(postinsql.bind(null, topicId), 4000);
meder omuraliev
la source
30
window.setTimeoutest 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 retard eval().
Miles
2
var temp = setTimeout (function () {postinsql (topicId);}, 4000); clearTimeout (temp); ??
Josh Mc
12
Que se passerait-il si topicId était modifié après la temporisation, mais avant l'appel de la fonction?
pilau
22
@pilau c'est exactement mon problème: si les variables utilisées dans la fonction anonyme changent avant le timeout (comme dans une boucle for) alors cela changera également à l'intérieur de la fonction. Donc, dans mon exemple, définir 5 délais différents dans une boucle for a fini par utiliser les mêmes variables. Soyez prudent lorsque vous utilisez cette réponse!
Cristian
10
@pilau en utilisant une autre fermeture aidera topicId = 12; fonction postinsql (topicId) {console.log (topicId); } fonction setTimeOutWithClosure (topicId) {setTimeout (function () {postinsql (topicId);}, 1000)} setTimeOutFunction (topicId); topicId = 13;
Halis Yılboğa
728

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:

var hello = "Hello World";
setTimeout(alert, 1000, hello);

Plus de détails:

Fabio Phms
la source
56
Je ne sais pas pourquoi cette réponse n'a pas été sélectionnée comme la meilleure. L'utilisation d'une fonction anonyme fonctionne, bien sûr, mais si vous pouvez simplement passer un troisième paramètre dans l'appel de fonction setTimeout d'origine ... pourquoi pas?
Kris Schouw
54
Parce que cela ne fonctionne pas dans les versions d'IE encore beaucoup à l'état sauvage.
Aaron
4
Cette réponse m'a en fait permis de passer un objet événement, les autres méthodes ne l'ont pas fait. J'avais déjà une fonction anonyme.
Glenn Plas
27
De bien meilleure réponse. Si vous avez du code qui modifie votre paramètre entre l'appel "setTimeout" et l'exécution réelle de la fonction anonyme - la fonction anonyme recevra la valeur modifiée, pas ce qu'elle était au moment de l'appel setTimeout. par exemple: pour (var i = 0; i <100; i ++) {setTimeout (function () {console.write (i);}, 0); } cela enregistrera "100" 100 fois (testé sur FF). La réponse actuelle permet d'éviter cela.
root
1
Selon developer.mozilla.org/es/docs/Web/API/WindowTimers/setTimeout, les arguments de rappel pour Internet Explorer ne sont pris en charge que dans les versions> = 10, soyez prudent car sur de nombreux sites ie8 et ie9 obtient toujours une part pertinente.
le0diaz
155

Après avoir fait quelques recherches et tests, la seule implémentation correcte est:

setTimeout(yourFunctionReference, 4000, param1, param2, paramN);

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.

Jiri Vetyska
la source
24
C'est avec tristesse dans mon cœur que je dois informer: cela ne fonctionne pas dans Internet Explorer. : / Tous les paramètres supplémentaires apparaissent comme non définis.
Amalgovinus
6
J'utilise justevar that = this; setTimeout( function() { that.foo(); }, 1000);
Ed Williams
2
C'est correct et cela est spécifié en HTML5. whatwg.org/specs/web-apps/current-work/multipage/…
Garrett
4
C'est exactement la même réponse que celle de Fabio .
Dan Dascalescu
1
Selon developer.mozilla.org/es/docs/Web/API/WindowTimers/setTimeout, les arguments de rappel pour Internet Explorer ne sont pris en charge que dans les versions> = 10, soyez prudent car sur de nombreux sites ie8 et ie9 obtient toujours une part pertinente.
le0diaz
45

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 :

_.delay = function(func, wait) {
  var args = slice.call(arguments, 2);
  return setTimeout(function(){ return func.apply(null, args); }, wait);
};

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.

David Meister
la source
7
Cette réponse fonctionne réellement mais vous semblez avoir une bibliothèque que je n'ai pas. Voici le petit correctif pour que cela fonctionne: au lieu de slice.call, utilisez Array.prototype.slice.call (arguments, 2)
Melanie
7
@Melanie "une bibliothèque"? J'ai dit dans la réponse que c'était la bibliothèque de soulignements - underscorejs.org . Mais oui, Array.prototype.slice est aliasé pour couper à l'intérieur de cette bibliothèque, donc vous devez le faire vous-même si vous ne l'utilisez pas, bon endroit :)
David Meister
38

J'ai récemment rencontré la situation unique d'avoir besoin d'utiliser un setTimeoutdans une boucle . Comprendre cela peut vous aider à comprendre comment transmettre des paramètres à setTimeout.

Méthode 1

Utilisez forEachet Object.keys, selon la suggestion de Sukima :

var testObject = {
    prop1: 'test1',
    prop2: 'test2',
    prop3: 'test3'
};

Object.keys(testObject).forEach(function(propertyName, i) {
    setTimeout(function() {
        console.log(testObject[propertyName]);
    }, i * 1000);
});

Je recommande cette méthode.

Méthode 2

Utilisation bind:

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }.bind(this, propertyName), i++ * 1000);
}

JSFiddle: http://jsfiddle.net/MsBkW/

Méthode 3

Ou si vous ne pouvez pas utiliser forEachou bind, utilisez un IIFE :

var i = 0;
for (var propertyName in testObject) {
    setTimeout((function(propertyName) {
        return function() {
            console.log(testObject[propertyName]);
        };
    })(propertyName), i++ * 1000);
}

Méthode 4

Mais si vous ne vous souciez pas d'IE <10, vous pouvez utiliser la suggestion de Fabio :

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }, i++ * 1000, propertyName);
}

Méthode 5 (ES6)

Utilisez une variable de portée de bloc:

let i = 0;
for (let propertyName in testObject) {
    setTimeout(() => console.log(testObject[propertyName]), i++ * 1000);
}

Bien que je recommanderais toujours d'utiliser Object.keysavec forEachdans ES6.

David Sherret
la source
2
Remarque: .bindne 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/1876899
cjspurgeon
1
Si vous êtes dans un environnement qui utilise bindalors vous aussi dans un environnement qui offre Object.keyset forEach. 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.
Sukima
@David Sherret au cas où vous ne l'auriez pas utilisé auparavant, consultez certainement la asyncbibliothè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 asynchrone forEach, map, reduce, etc.
mikermcneil
25

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 le thiscontexte):

setTimeout(postinsql.bind(null, topicId), 4000);

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

mourir
la source
ce contexte peut être passé avec le premier argument de bindsetTimeout(postinsql.bind(this, topicId), 4000);
Giuseppe Galano
@GiuseppeGalano totalement, je l'ai mentionné dans ma réponse, mais ce n'est pas nécessaire pour cet exemple :)
décédé
Fascinant combien de gloss sur des applications partielles utilisent bind. Cela donne vraiment du code lisible.
Sukima
bind () n'est pris en charge que par IE9 +, donc cette approche ne fonctionnera pas pour <IE9
Sanjeev
@Sanjeev Utilisez la cale ES5 pour la faire fonctionner dans les anciens IE: github.com/es-shims/es5-shim
gregers
17

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:

settopic=function(topicid){
  setTimeout(function(){
    //thanks to closure, topicid is visible here
    postinsql(topicid);
  },4000);
}

...
if (xhr.readyState==4){
  settopic(xhr.responseText);
}

Certains ont suggéré d'utiliser une fonction anonyme lors de l'appel de la fonction timeout:

if (xhr.readyState==4){
  setTimeout(function(){
    settopic(xhr.responseText);
  },4000);
}

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 .

Schien
la source
1
+1 pour une solution lisible, légèrement différente de la mienne. Pendant que vous avez le setTimeout à l'intérieur de la fonction settopic, j'ai la fonction fDelayed (votre settopic) à l'intérieur de la fonction setTimeout.
Dominic
11

Ma réponse:

setTimeout((function(topicId) {
  return function() {
    postinsql(topicId);
  };
})(topicId), 4000);

Explication:

La fonction anonyme créée renvoie une autre fonction anonyme. Cette fonction a accès à l'origine transmise topicId, donc elle ne fera pas d'erreur. La première fonction anonyme est immédiatement appelée, en passant topicId, de sorte que la fonction enregistrée avec un retard a accès topicIdau moment de l'appel, par le biais de fermetures.

OU

Cela se traduit essentiellement par:

setTimeout(function() {
  postinsql(topicId); // topicId inside higher scope (passed to returning function)
}, 4000);

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
C'est la meilleure réponse. Beaucoup de ces solutions n'honoreront même pas le délai d'attente. Cependant, pourquoi mettez-vous la première fonction anonyme entre parenthèses? Je ne pense pas qu'ils soient nécessaires pour y parvenir.
Robert Henderson
c'est la meilleure réponse 👍, mais a dû faire un clone car lorsque des valeurs comme topicIdsont modifiées, la valeur dans le délai d'attente change également. Un clone l'a corrigé
pariola le
10

Remplacer

 setTimeout("postinsql(topicId)", 4000);

avec

 setTimeout("postinsql(" + topicId + ")", 4000);

ou mieux encore, remplacez l'expression de chaîne par une fonction anonyme

 setTimeout(function () { postinsql(topicId); }, 4000);

ÉDITER:

Le commentaire de Brownstone est incorrect, cela fonctionnera comme prévu, comme démontré en l'exécutant dans la console Firebug

(function() {
  function postinsql(id) {
    console.log(id);
  }
  var topicId = 3
  window.setTimeout("postinsql(" + topicId + ")",4000); // outputs 3 after 4 seconds
})();

Notez que je suis d'accord avec les autres sur le fait que vous devez éviter de passer une chaîne à setTimeoutcar cela appellera eval()la chaîne et passera à la place une fonction.

Russ Cam
la source
Cela ne fonctionnera pas car le résultat de postinsql (topicId) sera exécuté par setTimeout. Vous devez l'encapsuler dans une fonction comme avec la première réponse, ou utiliser un assistant comme .curry () - setTimeout de Prototype (postinsql.curry (topidId), 4000);
shuckster le
2
@brownstone: C'est incorrect. La chaîne sera évaluée lorsque le délai d'expiration se déclenchera.
Miles
9

Vous pouvez passer le paramètre à la fonction de rappel setTimeout en tant que:

setTimeout (fonction, millisecondes, param1, param2, ...)

par exemple.

function myFunction() {
  setTimeout(alertMsg, 3000, "Hello");
}

function alertMsg(message) {
    alert(message)
}
Jatin Verma
la source
1
Quelqu'un peut-il me dire pourquoi cette réponse n'est pas la préférée? c'est le moyen le plus simple à mon avis! Aussi simple quesetTimeout( (p) => { console.log(p); }, 1000, "hi" );
Mazhar Zandsalimi
1
Ouais! Ce devrait être la réponse acceptée. De MDN: developer.mozilla.org/en-US/docs/Web/API/…
Han
5

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:

  1. Utiliser Param pour setTimeout
setTimeout(function(p){
//p == param1
},3000,param1);
  1. Utiliser l'expression de fonction immédiatement invoquée (IIFE)
let param1 = 'demon';
setTimeout(function(p){
    // p == 'demon'
},2000,(function(){
    return param1;
})()
);
  1. Solution à la question
function statechangedPostQuestion()
{
  //alert("statechangedPostQuestion");
  if (xmlhttp.readyState==4)
  {
    setTimeout(postinsql,4000,(function(){
        return xmlhttp.responseText;
    })());
  }
}

function postinsql(topicId)
{
  //alert(topicId);
}
Alpesh Patil
la source
4

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 si topicIdà l'extérieur elle sera modifiée peu de temps après.

var topicId = xmlhttp.responseText;
var fDelayed = function(tid) {
  return function() {
    postinsql(tid);
  };
}
setTimeout(fDelayed(topicId),4000);

ou court:

var topicId = xmlhttp.responseText;
setTimeout(function(tid) {
  return function() { postinsql(tid); };
}(topicId), 4000);
Dominique
la source
4

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 currentListvariable 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 variable currentListchange immédiatement après le code affiché, le setInterval()fera la bonne chose.

Sans cette technique IIFE, la setTimeout()fonction sera certainement appelée pour chaque h2élément du DOM, mais tous ces appels ne verront que la valeur textuelle du dernier h2 élément.

<script>
  // Wait for the document to load.
  $(document).ready(function() {
  $("h2").each(function (index) {

    currentList = $(this).text();

    (function (param1, param2) {
        setTimeout(function() {
            $("span").text(param1 + ' : ' + param2 );
        }, param1 * 1000);

    })(index, currentList);
  });
</script>
Gurjeet Singh
la source
4

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:

const someFunction = (params) => () => {
  //do whatever
};

setTimeout(someFunction(params), 1000);

Ou si someFunctionc'est la première commande:

setTimeout(() => someFunction(params), 1000); 
John Hartman
la source
c'est très incompatible
user151496
Élégant en effet! Merci
Velojet
3

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

gamelle
la source
3

Comment j'ai résolu cette étape?

juste comme ça :

setTimeout((function(_deepFunction ,_deepData){
    var _deepResultFunction = function _deepResultFunction(){
          _deepFunction(_deepData);
    };
    return _deepResultFunction;
})(fromOuterFunction, fromOuterData ) , 1000  );

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:

_deepFunction(_deepData);

// change to something like :
_deepFunction.apply(contextFromParams , args); 

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:

myDelay_function = function(fn , params , ctxt , _time){
setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.call(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// the function to be used :
myFunc = function(param){ console.log(param + this.name) }
// note that we call this.name

// a context object :
myObjet = {
    id : "myId" , 
    name : "myName"
}

// setting a parmeter
myParamter = "I am the outer parameter : ";

//and now let's make the call :
myDelay_function(myFunc , myParamter  , myObjet , 1000)

// this will produce this result on the console line :
// I am the outer parameter : myName

Vous pouvez peut-être modifier la signature pour la rendre plus conforme:

myNass_setTimeOut = function (fn , _time , params , ctxt ){
return setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.apply(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// and try again :
for(var i=0; i<10; i++){
   myNass_setTimeOut(console.log ,1000 , [i] , console)
}

Et enfin pour répondre à la question d'origine:

 myNass_setTimeOut( postinsql, 4000, topicId );

J'espère que cela peut aider!

ps: désolé mais l'anglais ce n'est pas ma langue maternelle!

Anonymous0day
la source
C'est trop compliqué par rapport à d'autres réponses.
Dan Dascalescu
3

cela fonctionne dans tous les navigateurs (IE est une excentrique)

setTimeout( (function(x) {
return function() {
        postinsql(x);
    };
})(topicId) , 4000);
user3756459
la source
3

si vous voulez passer une variable en paramètre, essayez ceci

si l'exigence est la fonction et var comme parmas alors essayez ceci

setTimeout((param1,param2) => { 
     alert(param1 + param2);
     postinsql(topicId);
},2000,'msg1', 'msg2')

si l'exigence n'est que des variables en tant que paramètres, essayez ceci

setTimeout((param1,param2) => { alert(param1 + param2) },2000,'msg1', 'msg2')

Vous pouvez essayer cela avec ES5 et ES6

homme fou
la source
2

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

function postinsql(topicId)
{
  //alert(topicId);
}
setTimeout(
       postinsql.apply(window,["mytopic"])
,500);
Vishnu Prasanth G
la source
1

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: -

handle = self.setTimeout( handler [, timeout [, arguments... ] ] )

Planifie une temporisation pour exécuter le gestionnaire après des millisecondes de temporisation. Tous les arguments sont transmis directement au gestionnaire.

setTimeout(postinsql, 4000, topicId);

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)

Garrett
la source
0

@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:

$('.targetItemClass').hover(ItemHoverIn, ItemHoverOut);

function ItemHoverIn() {
 //some code here
}

function ItemHoverOut() {
    var THIS = this;
    setTimeout(
        function () { ItemHoverOut_timeout(THIS); },
        100
    );
}
function ItemHoverOut_timeout(target) {
    //do something with target which is hovered out
}

J'espère que c'est utile pour quelqu'un d'autre.

Vladislav
la source
0

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:

var i = 0;
var hellos = ["Hello World1!", "Hello World2!", "Hello World3!", "Hello World4!", "Hello World5!"];

if(hellos.length > 0) timeout();

function timeout() {                
    document.write('<p>' + hellos[i] + '<p>');
    i++;
    if (i < hellos.length)
        setTimeout(timeout, 500);
}

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.

Vakhtang Tevdorashvili
la source
0

// Ce sont trois réponses très simples et concises:

function fun() {
    console.log(this.prop1, this.prop2, this.prop3);
}

let obj = { prop1: 'one', prop2: 'two', prop3: 'three' };

let bound = fun.bind(obj);

setTimeout(bound, 3000);

 // or

function funOut(par1, par2, par3) {

  return function() { 

    console.log(par1, par2, par3);

  }
};

setTimeout(funOut('one', 'two', 'three'), 5000);

 // or

let funny = function(a, b, c) { console.log(a, b, c); };

setTimeout(funny, 2000, 'hello', 'worldly', 'people');
Riches
la source
0

Répondre à la question mais par une simple fonction d'addition avec 2 arguments.

var x = 3, y = 4;

setTimeout(function(arg1, arg2) { 
      delayedSum(arg1, arg2);
}(x, y), 1000);

function delayedSum(param1, param2) {
     alert(param1 + param2); // 7
}
SridharKritha
la source
0

Vous devez supprimer les guillemets de votre setTimeOutappel de fonction comme ceci:

setTimeout(postinsql(topicId),4000);
Ghanshyam Sharma
la source
-1

Je pense que tu veux:

setTimeout("postinsql(" + topicId + ")", 4000);

la source
1
J'ai rencontré des cas où cela ne fonctionne tout simplement pas (ce qui entraîne toujours une erreur «fonction non définie») mais l'utilisation de la fonction anonyme fonctionne. Ce qui est frustrant étant donné que tout le monde semble dire que la syntaxe ci-dessus devrait toujours fonctionner. (pourrait-il être que jQuery gêne en quelque sorte la méthode 'quote as string'?)
DA.
6
Supposons que topicId soit une fonction ... Ou un objet. Ça ne marchera pas!
Serafeim
Si vous voulez vraiment continuer avec cette méthode, utilisez JSON.stringifypour les objets et les tableaux réguliers, puis utilisez l' JSON.parseintérieur de la fonction. Cependant, tout comportement sera perdu si l'objet a des méthodes.
DarthCadeus
-2

// Ce sont trois réponses très simples et concises:

function fun() {
    console.log(this.prop1, this.prop2, this.prop3);
}

let obj = { prop1: 'one', prop2: 'two', prop3: 'three' };

let bound = fun.bind(obj);

setTimeout(bound, 3000);

 // or

function funOut(par1, par2, par3) {

  return function() { 

    console.log(par1, par2, par3);

  }
};

setTimeout(funOut('one', 'two', 'three'), 5000);

 // or

let funny = function(a, b, c) { console.log(a, b, c); };

setTimeout(funny, 2000, 'hello', 'worldly', 'people');
user11385739
la source