Ich habe einen JavaScript-Code, der wie folgt aussieht:
function statechangedPostQuestion()
{
//alert("statechangedPostQuestion");
if (xmlhttp.readyState==4)
{
var topicId = xmlhttp.responseText;
setTimeout("postinsql(topicId)",4000);
}
}
function postinsql(topicId)
{
//alert(topicId);
}
Ich erhalte einen Fehler, der topicId
nicht definiert ist. Alles hat funktioniert, bevor ich die setTimeout()
Funktion verwendet habe.
Ich möchte, dass meine postinsql(topicId)
Funktion nach einiger Zeit aufgerufen wird. Was sollte ich tun?
javascript
parameters
callback
settimeout
Zeeshan Rang
quelle
quelle
Antworten:
Sie müssen eine anonyme Funktion als Parameter anstelle einer Zeichenfolge eingeben. Die letztere Methode sollte nicht einmal gemäß der ECMAScript-Spezifikation funktionieren, aber die Browser sind nur nachsichtig. Dies ist die richtige Lösung. Verlassen Sie sich niemals darauf, einen String als 'Funktion' zu übergeben, wenn Sie
setTimeout()
oder verwendensetInterval()
. Er ist langsamer, weil er ausgewertet werden muss und einfach nicht richtig ist.AKTUALISIEREN:
Wie Hobblin in seinen Kommentaren zur Frage sagte , können Sie jetzt Argumente an die Funktion in setTimeout mit übergeben
Function.prototype.bind()
.Beispiel:
quelle
window.setTimeout
ist eine DOM-Methode und als solche nicht in der ECMAScript-Spezifikation definiert. Das Übergeben einer Zeichenfolge hat in Browsern immer funktioniert und ist ein De-facto- Standard. Die Möglichkeit, ein Funktionsobjekt zu übergeben, wurde später mit JavaScript 1.2 hinzugefügt. Es ist explizit Teil der HTML5-Entwurfsspezifikation ( whatwg.org/specs/web) -apps / current-work / mehrseitig /… ). Die Verwendung einer Zeichenfolge anstelle eines Funktionsobjekts wird jedoch im Allgemeinen als schlechter Stil angesehen, da es sich im Wesentlichen um eine Form der Verzögerung handelteval()
.In modernen Browsern empfängt das "setTimeout" einen dritten Parameter, der am Ende des Timers als Parameter an die interne Funktion gesendet wird.
Beispiel:
Mehr Details:
quelle
Nach einigen Recherchen und Tests ist die einzig richtige Implementierung:
setTimeout übergibt alle zusätzlichen Parameter an Ihre Funktion, damit sie dort verarbeitet werden können.
Die anonyme Funktion kann für sehr grundlegende Dinge funktionieren, aber innerhalb eines Objekts, in dem Sie "this" verwenden müssen, gibt es keine Möglichkeit, es zum Laufen zu bringen. Jede anonyme Funktion ändert "dies" so, dass sie auf das Fenster zeigt, sodass Sie Ihre Objektreferenz verlieren.
quelle
var that = this; setTimeout( function() { that.foo(); }, 1000);
Dies ist eine sehr alte Frage mit einer bereits "richtigen" Antwort, aber ich dachte, ich würde einen anderen Ansatz erwähnen, den hier niemand erwähnt hat. Dies wird aus der ausgezeichneten Unterstrichbibliothek kopiert und eingefügt :
Sie können beliebig viele Argumente übergeben , wie Sie durch setTimeout genannt auf die Funktion möchten und als zusätzlichen Bonus (gut, in der Regel ein Bonus) der Wert der übergebenen Argumente an Ihre Funktion eingefroren sind , wenn Sie setTimeout rufen, so dass , wenn sie Wert zu ändern Irgendwann zwischen dem Aufruf von setTimeout () und dem Timeout, na ja ... das ist nicht mehr so schrecklich frustrierend :)
Hier ist eine Geige, in der Sie sehen können, was ich meine.
quelle
Ich bin kürzlich auf die einzigartige Situation gestoßen, eine
setTimeout
in einer Schleife verwenden zu müssen . Wenn Sie dies verstehen, können Sie besser verstehen, wie Parameter übergeben werdensetTimeout
.Methode 1
Verwenden Sie
forEach
undObject.keys
gemäß Sukimas Vorschlag :Ich empfehle diese Methode.
Methode 2
Verwendung
bind
:JSFiddle: http://jsfiddle.net/MsBkW/
Methode 3
Oder wenn Sie nicht verwenden können ,
forEach
oderbind
verwenden Sie ein IIFE :Methode 4
Wenn Sie sich jedoch nicht für IE <10 interessieren, können Sie Fabios Vorschlag verwenden :
Methode 5 (ES6)
Verwenden Sie eine Variable mit Blockbereich:
Obwohl ich immer noch empfehlen würde,
Object.keys
mitforEach
in ES6 zu verwenden.quelle
.bind
nicht für IE8 und niedriger [ref: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ]. Am Ende habe ich Schiens Lösung verwendet: stackoverflow.com/a/21213723/1876899bind
dann sind Sie auch in einer Umgebung, dieObject.keys
und bietetforEach
. Sie können die for-Schleife verlieren und dabei einen "freien" Funktionsumfang (wie bei zwei Vögeln mit einer Klappe frei, nicht ressourcenfrei) erhalten.async
Bibliothek an ( github.com/caolan/async ). Wir verwenden es ausgiebig in Segeln und haben in den letzten 2 Jahren großartige Ergebnisse erzielt. Es stellt Verfahren in sowohl parallel als auch in Serie für asynchroneforEach
,map
,reduce
usw.Hobblin hat dies bereits zu der Frage kommentiert, aber es sollte wirklich eine Antwort sein!
Die Verwendung
Function.prototype.bind()
ist der sauberste und flexibelste Weg, dies zu tun (mit dem zusätzlichen Vorteil, denthis
Kontext festlegen zu können ):Weitere Informationen finden Sie unter diesen MDN-Links:
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
quelle
setTimeout(postinsql.bind(this, topicId), 4000);
bind
. Es sorgt wirklich für lesbaren Code.Einige Antworten sind richtig, aber verworren.
Ich beantworte dies 4 Jahre später erneut, weil ich immer noch auf übermäßig komplexen Code stoße, um genau diese Frage zu lösen. Es gibt eine elegante Lösung.
Übergeben Sie beim Aufrufen von setTimeout zunächst keinen String als ersten Parameter, da dadurch die langsame Funktion "eval" effektiv aufgerufen wird.
Wie übergeben wir einen Parameter an eine Timeout-Funktion? Durch Verwendung von Verschluss:
Einige haben vorgeschlagen, beim Aufrufen der Timeout-Funktion eine anonyme Funktion zu verwenden:
Die Syntax funktioniert. Zu dem Zeitpunkt, zu dem Settopic aufgerufen wird, dh 4 Sekunden später, ist das XHR-Objekt möglicherweise nicht mehr dasselbe. Daher ist es wichtig, die Variablen vorab zu binden .
quelle
Meine Antwort:
Erläuterung:
ODER
Dies konvertiert im Grunde zu:
EDIT: Ich habe die gleiche Antwort gesehen, also schau dir seine an. Aber ich habe seine Antwort nicht gestohlen! Ich habe nur vergessen zu schauen. Lesen Sie die Erklärung und prüfen Sie, ob es hilfreich ist, den Code zu verstehen.
quelle
topicId
der Wert im Timeout ändert, wenn Werte wie geändert werden. Ein Klon hat es behobenErsetzen
mit
oder noch besser, ersetzen Sie den Zeichenfolgenausdruck durch eine anonyme Funktion
BEARBEITEN:
Brownstones Kommentar ist falsch. Dies funktioniert wie beabsichtigt, wie durch Ausführen in der Firebug-Konsole gezeigt wird
Beachten Sie, dass ich mit anderen einverstanden bin, dass Sie vermeiden sollten, eine Zeichenfolge zu übergeben,
setTimeout
da dieseval()
die Zeichenfolge aufruft und stattdessen eine Funktion übergibt .quelle
Sie können den Parameter wie folgt an die Rückruffunktion setTimeout übergeben:
setTimeout (Funktion, Millisekunden, param1, param2, ...)
z.B.
quelle
setTimeout( (p) => { console.log(p); }, 1000, "hi" );
Die einfachste browserübergreifende Lösung zur Unterstützung von Parametern in setTimeout:
Wenn es Ihnen nichts ausmacht, IE 9 und niedriger nicht zu unterstützen:
https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
quelle
Ich weiß, dass diese Frage vor 10 Jahren gestellt wurde, aber wenn Sie bis hierher gescrollt haben, gehe ich davon aus, dass Sie immer noch vor einem Problem stehen. Die Lösung von Meder Omuraliev ist die einfachste und mag den meisten von uns helfen, aber für diejenigen, die keine Bindung haben möchten, hier ist sie:
quelle
Ich weiß, dass es alt ist, aber ich wollte meinen (bevorzugten) Geschmack hinzufügen.
Ich denke, ein ziemlich lesbarer Weg, dies zu erreichen, besteht darin, das
topicId
an eine Funktion zu übergeben, die wiederum das Argument verwendet, um die Themen-ID intern zu referenzieren. Dieser Wert ändert sich auch dann nicht, wenn ertopicId
kurz darauf von außen geändert wird.oder kurz:
quelle
Die Antwort von David Meister scheint sich um Parameter zu kümmern, die sich unmittelbar nach dem Aufruf von setTimeout (), jedoch vor dem Aufruf der anonymen Funktion ändern können. Aber es ist zu umständlich und nicht sehr offensichtlich. Ich habe eine elegante Methode entdeckt, mit IIFE (sofort aufgerufener Funktionsausdruck) so ziemlich dasselbe zu tun.
Im folgenden Beispiel wird die
currentList
Variable an das IIFE übergeben, wodurch sie beim Schließen gespeichert wird, bis die verzögerte Funktion aufgerufen wird. Selbst wenn sich die VariablecurrentList
unmittelbar nach dem angezeigten Code ändert,setInterval()
wird die Variable das Richtige tun.Ohne diese IIFE-Technik wird die
setTimeout()
Funktion definitiv für jedesh2
Element im DOM aufgerufen , aber bei all diesen Aufrufen wird nur der Textwert des letztenh2
Elements angezeigt .quelle
Wenn Sie eine Funktion als Rückruf mit bestimmten Parametern übergeben müssen, können Sie im Allgemeinen Funktionen höherer Ordnung verwenden. Dies ist ziemlich elegant mit ES6:
Oder wenn
someFunction
ist erste Bestellung:quelle
Beachten Sie, dass der Grund, warum topicId gemäß der Fehlermeldung "nicht definiert" wurde, darin besteht, dass es als lokale Variable vorhanden war, als setTimeout ausgeführt wurde, jedoch nicht, als der verzögerte Aufruf von postinsql erfolgte. Die variable Lebensdauer ist besonders wichtig, insbesondere wenn Sie versuchen, "dies" als Objektreferenz zu übergeben.
Ich habe gehört, dass Sie topicId als dritten Parameter an die Funktion setTimeout übergeben können. Es werden nicht viele Details angegeben, aber ich habe genug Informationen, damit es funktioniert, und es ist in Safari erfolgreich. Ich weiß allerdings nicht, was sie mit dem "Millisekundenfehler" meinen. Schau es dir hier an:
http://www.howtocreate.co.uk/tutorials/javascript/timers
quelle
Wie habe ich diese Phase gelöst?
genau so :
setTimeout wartet auf einen Verweis auf eine Funktion, also habe ich ihn in einem Closure erstellt, der meine Daten interpretiert und eine Funktion mit einer guten Instanz meiner Daten zurückgibt!
Vielleicht können Sie diesen Teil verbessern:
Ich habe es auf Chrome, Firefox und IE getestet und es funktioniert gut. Ich weiß nichts über die Leistung, aber ich brauchte es, um zu funktionieren.
ein Beispieltest:
Vielleicht können Sie die Signatur ändern, um sie komfortabler zu gestalten:
Und schließlich zur Beantwortung der ursprünglichen Frage:
Hoffe es kann helfen!
ps: sorry aber englisch es ist nicht meine muttersprache!
quelle
Dies funktioniert in allen Browsern (IE ist ein seltsamer Ball)
quelle
Wenn Sie eine Variable als Parameter übergeben möchten, versuchen Sie dies
Wenn die Anforderung Funktion und Var als Parmas ist, versuchen Sie dies
Wenn die Anforderung nur Variablen als Parameter sind, versuchen Sie dies
Sie können dies mit ES5 und ES6 versuchen
quelle
Sie können die Standardfunktionalität von 'apply ()' wie folgt ausprobieren. Sie können mehr Argumente als Ihre Anforderung im Array übergeben
quelle
setTimeout ist Teil des von WHAT WG definierten DOM.
https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html
Die gewünschte Methode ist: -
Anscheinend werden zusätzliche Argumente in IE10 unterstützt. Alternativ können Sie verwenden
setTimeout(postinsql.bind(null, topicId), 4000);
, das Übergeben zusätzlicher Argumente ist jedoch einfacher, und das ist vorzuziehen.Historisches Faktoid: In Tagen von VBScript war in JScript der dritte Parameter von setTimeout die Sprache als Zeichenfolge, standardmäßig "JScript", jedoch mit der Option "VBScript". https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa741500(v%3Dvs.85)
quelle
@Jiri Vetyska danke für den Beitrag, aber in deinem Beispiel stimmt etwas nicht. Ich musste das schwebende Ziel (dies) an eine Zeitüberschreitungsfunktion übergeben und habe Ihren Ansatz ausprobiert. In IE9 getestet - funktioniert nicht. Ich habe auch einige Nachforschungen angestellt und es scheint, dass der dritte Parameter , wie hier gezeigt, die verwendete Skriptsprache ist. Keine Erwähnung über zusätzliche Parameter.
Also folgte ich der Antwort von @ meder und löste mein Problem mit diesem Code:
Hoffe, das ist nützlich für jemand anderen.
quelle
Da es im IE ein Problem mit dem dritten optonalen Parameter gibt und die Verwendung von Verschlüssen verhindert, dass wir die Variablen ändern (z. B. in einer Schleife) und dennoch das gewünschte Ergebnis erzielen, schlage ich die folgende Lösung vor.
Wir können versuchen, Rekursion wie folgt zu verwenden:
Wir müssen sicherstellen, dass nichts anderes diese Variablen ändert und dass wir eine ordnungsgemäße Rekursionsbedingung schreiben, um eine unendliche Rekursion zu vermeiden.
quelle
// Dies sind drei sehr einfache und prägnante Antworten:
quelle
Beantwortung der Frage aber durch eine einfache Additionsfunktion mit 2 Argumenten.
quelle
Sie müssen Anführungszeichen
setTimeOut
wie folgt aus Ihrem Funktionsaufruf entfernen :quelle
Ich denke du willst:
quelle
JSON.stringify
für reguläre Objekte und Arrays und verwenden Sie sie dannJSON.parse
innerhalb der Funktion. Das gesamte Verhalten geht jedoch verloren, wenn das Objekt über Methoden verfügt.// Dies sind drei sehr einfache und prägnante Antworten:
quelle