Frage

Ich habe einige JavaScript-Code, der aussieht wie:

function statechangedPostQuestion()
{
  //alert("statechangedPostQuestion");
  if (xmlhttp.readyState==4)
  {
    var topicId = xmlhttp.responseText;
    setTimeout("postinsql(topicId)",4000);
  }
}

function postinsql(topicId)
{
  //alert(topicId);
}

ich eine Fehlermeldung erhalten, dass topicId nicht definiert Alles funktioniert, bevor ich die setTimeout() Funktion verwendet.

Ich möchte meine postinsql(topicId) Funktion nach einiger Zeit aufgerufen werden. Was soll ich tun?

War es hilfreich?

Lösung

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

Sie müssen eine anonyme Funktion als Parameter anstelle einer Zeichenfolge füttern, sollte die letztgenannte Methode nicht einmal Arbeit gemäß der ECMAScript-Spezifikation aber Browser ist nur nachsichtig. Dies ist die richtige Lösung, nicht immer verlassen sich auf eine Zeichenfolge als ‚Funktion‘ vorbei, wenn setTimeout() oder setInterval() verwenden, es ist langsamer, weil sie ausgewertet werden muss, und es ist einfach nicht richtig.

UPDATE:

Wie sagte Hobblin in seiner Stellungnahme auf die Frage, jetzt können Sie Argumente für die Funktion innerhalb SetTimeout passieren können mit Function.prototype.bind()

Beispiel:

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

Andere Tipps

In modernen Browsern, die „setTimeout“ erhält einen dritten Parameter, der als Parameter an die internen Funktion am Ende des Timers gesendet wird.

Beispiel:

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

Weitere Informationen:

Nach einigen Recherchen und Tests, die einzig richtige Umsetzung ist:

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

SetTimeout werden alle zusätzlichen Parameter an die Funktion übergeben, so dass sie dort verarbeitet werden können.

Die anonyme Funktion für sehr grundlegenden Dinge funktionieren kann, aber innerhalb Instanz eines Objekts, in dem Sie verwenden müssen „dieser“, gibt es keine Möglichkeit, es zu machen Arbeit. Jeder anonyme Funktion wird sich ändern „dieses“ Punkt-Fenster, so dass Sie Ihre Objektverweis verlieren.

Dies ist eine sehr alte Frage mit einer bereits „richtigen“ Antwort, aber ich dachte, dass ich eine anderen Ansatz erwähnen würde, dass niemand hier erwähnt hat. Dies wird kopiert und eingefügt von der ausgezeichneten Strich Bibliothek:

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

Sie können so viele Argumente übergeben, wie Sie auf die Funktion von setTimeout genannt möchten und als zusätzlichen Bonus (gut, in der Regel ein Bonus) den Wert der Argumente an die Funktion übergeben werden eingefroren wenn Sie anrufen setTimeout, so dass, wenn sie irgendwann zwischen Wert ändern, wenn setTimeout () aufgerufen wird und wenn es mal aus, na ja ..., die nicht so scheußlich ist frustrierend mehr:)

Hier ist eine Geige wo man sehen kann, was ich meine.

Ich kam vor kurzem in der einzigartigen Lage, um eine setTimeout in einer Schleife verwenden . Dieses Verständnis kann Ihnen helfen, zu verstehen, wie Parameter setTimeout zu übergeben.

Methode 1

Mit forEach und Object.keys, wie pro Sukima der Vorschlag :

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

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

ich diese Methode empfehlen.

Methode 2

Verwenden 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/

Methode 3

Oder wenn Sie nicht forEach oder bind verwenden können, verwenden Sie eine IIFE :

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

Methode 4

Aber wenn Sie nicht über IE egal <10, dann könnte man Fabios Vorschlag :

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

Methode 5 (ES6)

Verwenden Sie einen Block scoped Variable:

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

Obwohl ich immer noch mit Object.keys in ES6 mit forEach empfehlen würde.

Hobblin bereits kommentierte dies auf die Frage, aber es sollte eine Antwort wirklich sein!

Function.prototype.bind() Verwendung ist die sauberste und flexible Art und Weise, dies zu tun (mit dem zusätzlichen Bonus zu können, den this Kontext eingestellt):

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

Weitere Informationen finden Sie diese MDN Links:
https://developer.mozilla.org/en/docs/DOM/window.setTimeout#highlighter_547041 https://developer.mozilla.org/en/docs/JavaScript/Reference/ Global_Objects / Funktion / bind # With_setTimeout

sind einige Antworten korrekt, aber verworren.

Ich antworte auch in diese, 4 Jahre später, weil ich immer noch in allzu komplexen Code ausführen genau diese Frage zu lösen. Es ist eine elegante Lösung.

Zu allererst nicht passieren in einem String als ersten Parameter, wenn SetTimeout Aufruf, weil es effektiv einen Aufruf an die langsamen „eval“ -Funktion aufruft.

Wie können wir also in einem Parameter zu einer Timeout-Funktion übergeben? Durch die Verwendung von Schließung:

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

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

Einige haben mit anonymen Funktion vorgeschlagen, wenn die Timeout-Funktion aufrufen:

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

Die Syntax funktioniert. Aber durch die Zeit settopic genannt wird, das heißt 4 Sekunden später kann das XHR-Objekt nicht gleich sein. Daher ist es wichtig zu pre-bind der Variablen .

Meine Antwort:

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

Erklärung:

  

Die anonyme Funktion erstellt kehrt eine andere anonyme Funktion. Diese Funktion hat Zugriff auf die ursprünglich topicId weitergegeben, so wird es nicht einen Fehler machen. Die erste anonyme Funktion wird sofort aufgerufen, in topicId vorbei, so dass die registrierte Funktion mit einer Verzögerung Zugriff auf topicId zum Zeitpunkt des Aufrufs hat, durch Verschlüsse.

oder

Dieser wandelt grundsätzlich:

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

EDIT: Ich habe die gleiche Antwort sah, so Blick auf seine. Aber ich habe nicht stehlen seine Antwort! Ich habe vergessen, nur um zu sehen. Lesen Sie die Erklärung und sehen, ob es um den Code zu verstehen hilft.

Ersetzen

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

mit

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

oder besser noch, ersetzen Sie den String-Ausdruck mit einer anonymen Funktion

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

EDIT:

Brownstone Kommentar ist falsch, das wird wie vorgesehen funktionieren, wie es läuft dies in der Firebug-Konsole demonstriert

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

Beachten Sie, dass ich in agreeance mit anderen bin, dass Sie eine Zeichenfolge an setTimeout, da dies vorbei vermeiden sollte, wird eval() auf der Saite aufrufen und stattdessen eine Funktion übergeben.

Die einfachste Cross-Browser-Lösung für die Parameter in SetTimeout unterstützt:

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

Wenn Sie nichts dagegen haben die Unterstützung nicht IE 9 und senken:

setTimeout(postinsql, 4000, topicId);

setTimeout Desktop-Browser-Kompatibilität

SetTimeout mobile Browser-Kompatibilität

https://developer.mozilla.org/en- US / docs / Web / API / WindowTimers / setTimeout

Ich weiß, es ist alt, aber ich wollte meinen (bevorzugt) Geschmack zu dieser hinzuzufügen.

Ich denke, eine ziemlich lesbare Art und Weise, dies zu erreichen ist die topicId an eine Funktion zu übergeben, die wiederum das Argument verwendet das Thema ID intern zu verweisen. Dieser Wert wird nicht selbst wenn topicId wird nach geändert wird in Kürze in der Außenseite ändern.

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

oder kurz:

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

Die Antwort von David Meister scheint Pflege von Parametern zu nehmen, die zu SetTimeout nach dem Anruf sofort ändern können (), aber vor der anonyme Funktion aufgerufen wird. Aber es ist zu umständlich und nicht sehr offensichtlich. Ich entdeckte eine elegante Art und Weise so ziemlich die gleiche Sache mit IIFE tun (sofort inviked Funktionsausdruck).

Im Beispiel unten wird die currentList Variable auf den IIFE übergeben, die es in seiner Schließung spart, bis die verzögerte Funktion aufgerufen wird. Auch wenn die Variable currentList ändert sich sofort nach dem Code gezeigt, der setInterval() wird das Richtige tun.

Ohne diese IIFE Technik wird die setTimeout() Funktion auf jeden Fall für jedes h2 Element im DOM gecallt, aber all diese Anrufe nur den Textwert des letzten h2 Elements sehen.

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

Dies funktioniert in allen Browsern (IE ist ein oddball)

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

In der Regel, wenn Sie eine Funktion als Callback mit spezifischen Parameter zu übergeben müssen, können Sie Funktionen höherer Ordnung verwenden. Das ist ziemlich elegant mit ES6:

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

setTimeout(someFunction(params), 1000);

Oder wenn someFunction erste Ordnung:

setTimeout(() => someFunction(params), 1000); 

Beachten Sie, dass der Grund topicId wurde „nicht definiert“ pro der Fehlermeldung ist, dass es als eine lokale Variable existiert, wenn die setTimeout ausgeführt wurde, aber nicht, wenn das verzögerte Aufruf postinsql passiert ist. Variable Lebensdauer ist besonders wichtig, um Aufmerksamkeit zu widmen, vor allem, wenn so etwas wie nebenbei „diesen“ als Objektreferenz zu versuchen.

Ich habe gehört, dass Sie topicId als dritter Parameter an die setTimeout-Funktion übergeben können. Nicht viel Detail gegeben, aber ich habe genügend Informationen, um es an die Arbeit, und es ist erfolgreich in Safari. Ich weiß nicht, was sie über die „Millisekunden Fehler“ bedeuten though. Check it out hier:

http://www.howtocreate.co.uk/tutorials/javascript/timers

Wie ich diese Phase gelöst?

einfach so:

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

SetTimeout einen Verweis auf eine Funktion warten, so dass ich schaffte es in einem Verschluss, der meine Daten interpretiert und gibt eine Funktion mit einem guten Beispiel meiner Daten!

Vielleicht können Sie diesen Teil verbessern:

_deepFunction(_deepData);

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

Ich habe es getestet auf Chrome, Firefox und IE und ausführt gut, ich weiß nicht, über die Leistung, aber ich brauchte es zu funktionieren.

ein Beispieltest:

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

Vielleicht können Sie die Signatur ändern, um es mehr complient zu machen:

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)
}

Und endlich die ursprüngliche Frage zu beantworten:

 myNass_setTimeOut( postinsql, 4000, topicId );

Hope es kann helfen!

ps: sorry, aber Englisch es ist nicht meine Muttersprache

Wenn Sie wollen Variable übergeben als param Auf diese Weise können versuchen

, wenn Bedarf ist Funktion und var als Parmas dann versuchen, diese

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

wenn Anforderung nur Variablen als params ist dann versuchen, diese

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

Sie können versuchen, diese mit ES5 und ES6

Sie können versuchen, Standardfunktionalität von ‚apply ()‘ so etwas wie dieses, können Sie eine größere Anzahl von Argumenten als Ihre Anforderung im Array

übergeben
function postinsql(topicId)
{
  //alert(topicId);
}
setTimeout(
       postinsql.apply(window,["mytopic"])
,500);

Sie können die Parameter an die setTimeout Callback-Funktion übergeben, wie:

setTimeout (Funktion, Millisekunden, param1, param2, ...)

zB.

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

function alertMsg(message) {
    alert(message)
}

@Jiri Vetyska Dank für die Post, aber es ist etwas falsch in Ihrem Beispiel. Ich brauchte das Ziel zu passieren, die (das) zu einer Zeitüberschreitung Funktion schwebt aus ist und ich versuchte, Ihren Ansatz. Getestet in IE9 - funktioniert nicht. Ich habe auch einige der Forschung gemacht und es scheint, dass als spitzer hier den dritten Parameter ist die Skriptsprache verwendet werden. Keine Erwähnung über zusätzliche Parameter.

So folgte ich @ meder Antwort und löste mein Problem mit diesem 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
}

Hope, das ist sehr nützlich für jemand anderen.

Da gibt es ein Problem mit dem dritten optonal Parameter in IE und mit Schließungen hindert uns daran, die Variablen zu ändern (in einer Schleife zum Beispiel) und immer noch das gewünschte Ergebnis zu erreichen, schlage ich folgende Lösung.

Wir können versuchen, Rekursion wie folgt aus:

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);
}

Wir müssen sicherstellen, dass nichts anderes diese Variablen ändert und dass wir eine richtige Rekursion Bedingung schreiben unendliche Rekursion zu vermeiden.

// Das sind drei sehr einfache und präzise Antworten:

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');

Ich glaube, Sie wollen:

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

// Das sind drei sehr einfache und präzise Antworten:

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');
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top