Ich möchte ein JavaScript-Programm zwingen, an bestimmten Punkten seiner Ausführung zu warten, bis sich eine Variable geändert hat. Gibt es eine Möglichkeit, dies zu tun? Ich habe bereits eine Erweiterung namens "narratives JavaScript" gefunden, die das Programm zwingt, auf das Eintreten eines Ereignisses zu warten. Gibt es eine Möglichkeit, ein neues Ereignis zu erstellen, beispielsweise ein "Variablenänderungsereignis", das sich wie ein Ereignis mit einem Klick verhält?
javascript
variables
wait
Thanasis Petsas
quelle
quelle
Antworten:
Edit 2018: Bitte schauen Sie sich Object Getter und Setter und Proxies an . Alte Antwort unten:
Eine schnelle und einfache Lösung lautet wie folgt:
var something=999; var something_cachedValue=something; function doStuff() { if(something===something_cachedValue) {//we want it to match setTimeout(doStuff, 50);//wait 50 millisecnds then recheck return; } something_cachedValue=something; //real action } doStuff();
quelle
something===something_cachedValue
. Dann funktioniert es: jsfiddle.net/pEnYCJavaScript-Interpreter sind Single-Threaded-Interpreter, sodass sich eine Variable niemals ändern kann, wenn der Code in einem anderen Code wartet, der die Variable nicht ändert.
Meiner Meinung nach wäre es die beste Lösung, die Variable in eine Art Objekt zu verpacken, das eine Getter- und Setter-Funktion hat. Sie können dann eine Rückruffunktion in dem Objekt registrieren, das aufgerufen wird, wenn die Setterfunktion des Objekts aufgerufen wird. Sie können dann die Getter-Funktion im Rückruf verwenden, um den aktuellen Wert abzurufen:
function Wrapper(callback) { var value; this.set = function(v) { value = v; callback(this); } this.get = function() { return value; } }
Dies könnte leicht wie folgt verwendet werden:
<html> <head> <script type="text/javascript" src="wrapper.js"></script> <script type="text/javascript"> function callback(wrapper) { alert("Value is now: " + wrapper.get()); } wrapper = new Wrapper(callback); </script> </head> <body> <input type="text" onchange="wrapper.set(this.value)"/> </body> </html>
quelle
Ich würde einen Wrapper empfehlen, der den geänderten Wert verarbeitet. Zum Beispiel können Sie eine JavaScript-Funktion haben, wie folgt:
function Variable(initVal, onChange) { this.val = initVal; //Value to be stored in this object this.onChange = onChange; //OnChange handler //This method returns stored value this.GetValue = function() { return this.val; } //This method changes the value and calls the given handler this.SetValue = function(value) { this.val = value; this.onChange(); } }
Und dann können Sie daraus ein Objekt erstellen, das den Wert enthält, den Sie überwachen möchten, sowie eine Funktion, die aufgerufen wird, wenn der Wert geändert wird. Wenn Sie beispielsweise benachrichtigt werden möchten, wenn sich der Wert ändert und der Anfangswert 10 ist, schreiben Sie Code wie folgt:
var myVar = new Variable(10, function(){alert("Value changed!");});
Der Handler
function(){alert("Value changed!");}
wird aufgerufen (wenn Sie sich den Code ansehen), wenn erSetValue()
aufgerufen wird.Sie können Wert wie folgt erhalten:
Sie können den Wert folgendermaßen einstellen:
myVar.SetValue(12);
Unmittelbar danach wird eine Warnung auf dem Bildschirm angezeigt. Sehen Sie, wie es funktioniert: http://jsfiddle.net/cDJsB/
quelle
Die Frage wurde vor langer Zeit gestellt, viele Antworten bündeln das Ziel regelmäßig und verursachen unnötige Ressourcenverschwendung, wenn das Ziel unverändert bleibt. Darüber hinaus blockieren die meisten Antworten das Programm nicht, während sie auf Änderungen warten, die im ursprünglichen Beitrag gefordert werden.
Wir können jetzt eine Lösung anwenden, die rein ereignisgesteuert ist.
Die Lösung verwendet das Ereignis onClick, um ein Ereignis bereitzustellen, das durch eine Wertänderung ausgelöst wird.
Die Lösung kann in modernen Browsern ausgeführt werden, die Promise und async / await unterstützen. Wenn Sie Node.js verwenden, sollten Sie EventEmitter als bessere Lösung in Betracht ziehen .
<!-- This div is the trick. --> <div id="trick" onclick="onTrickClick()" /> <!-- Someone else change the value you monitored. In this case, the person will click this button. --> <button onclick="changeValue()">Change value</button> <script> // targetObj.x is the value you want to monitor. const targetObj = { _x: 0, get x() { return this._x; }, set x(value) { this._x = value; // The following line tells your code targetObj.x has been changed. document.getElementById('trick').click(); } }; // Someone else click the button above and change targetObj.x. function changeValue() { targetObj.x = targetObj.x + 1; } // This is called by the trick div. We fill the details later. let onTrickClick = function () { }; // Use Promise to help you "wait". This function is called in your code. function waitForChange() { return new Promise(resolve => { onTrickClick = function () { resolve(); } }); } // Your main code (must be in an async function). (async () => { while (true) { // The loop is not for pooling. It receives the change event passively. await waitForChange(); // Wait until targetObj.x has been changed. alert(targetObj.x); // Show the dialog only when targetObj.x is changed. await new Promise(resolve => setTimeout(resolve, 0)); // Making the dialog to show properly. You will not need this line in your code. } })(); </script>
quelle
Sie können Eigenschaften verwenden :
Object.defineProperty MDN-Dokumentation
Beispiel:
function def(varName, onChange) { var _value; Object.defineProperty(this, varName, { get: function() { return _value; }, set: function(value) { if (onChange) onChange(_value, value); _value = value; } }); return this[varName]; } def('myVar', function (oldValue, newValue) { alert('Old value: ' + oldValue + '\nNew value: ' + newValue); }); myVar = 1; // alert: Old value: undefined | New value: 1 myVar = 2; // alert: Old value: 1 | New value: 2
quelle
Super veraltet, aber sicherlich gute Möglichkeiten, dies unterzubringen. Ich habe das gerade für ein Projekt geschrieben und dachte, ich würde es teilen. Ähnlich wie bei einigen anderen, unterschiedlich im Stil.
var ObjectListener = function(prop, value) { if (value === undefined) value = null; var obj = {}; obj.internal = value; obj.watcher = (function(x) {}); obj.emit = function(fn) { obj.watch = fn; }; var setter = {}; setter.enumerable = true; setter.configurable = true; setter.set = function(x) { obj.internal = x; obj.watcher(x); }; var getter = {}; getter.enumerable = true; getter.configurable = true; getter.get = function() { return obj.internal; }; return (obj, Object.defineProperty(obj, prop, setter), Object.defineProperty(obj, prop, getter), obj.emit, obj); }; user._licenseXYZ = ObjectListener(testProp); user._licenseXYZ.emit(testLog); function testLog() { return function() { return console.log([ 'user._licenseXYZ.testProp was updated to ', value ].join(''); }; } user._licenseXYZ.testProp = 123;
quelle
Alternativ können Sie eine Funktion erstellen, die Aufgaben basierend auf dem Wert ihrer "statischen" Variablen ausführt. Beispiel unten:
<!DOCTYPE html> <div id="Time_Box"> Time </div> <button type="button" onclick='Update_Time("on")'>Update Time On</button> <button type="button" onclick='Update_Time("off")'>Update Time Off</button> <script> var Update_Time = (function () { //_____________________________________________________________ var Static = []; //"var" declares "Static" variable as static object in this function return function (Option) { var Local = []; //"var" declares "Local" variable as local object in this function if (typeof Option === 'string'){Static.Update = Option}; if (Static.Update === "on"){ document.getElementById("Time_Box").innerText = Date(); setTimeout(function(){Update_Time()}, 1000); //update every 1 seconds }; }; })(); Update_Time('on'); //turns on time update </script>
quelle
Was für mich funktioniert hat (ich habe überall nachgesehen und schließlich den jsfiddler von jemandem verwendet / es leicht modifiziert - hat gut funktioniert), war, diese Variable auf ein Objekt mit einem Getter und einem Setter zu setzen, und der Setter löst die Funktion aus, auf die er wartet Variablenänderung.
var myVariableImWaitingOn = function (methodNameToTriggerWhenChanged){ triggerVar = this; triggerVar.val = ''; triggerVar.onChange = methodNameToTriggerWhenChanged; this.SetValue(value){ if (value != 'undefined' && value != ''){ triggerVar.val = value; //modify this according to what you're passing in - //like a loop if an array that's only available for a short time, etc triggerVar.onChange(); //could also pass the val to the waiting function here //or the waiting function can just call myVariableImWaitingOn.GetValue() } }; this.GetValue(){ return triggerVar.val(); }; };
quelle
JavaScript ist eine der schlechtesten Programm- / Skriptsprachen aller Zeiten!
"Warten" scheint in JavaScript unmöglich zu sein! (Ja, wie im wirklichen Leben ist manchmal Warten die beste Option!)
Ich habe "while" -Schleife und "Rekursion" versucht (eine Funktion ruft sich wiederholt auf, bis ...), aber JavaScript funktioniert trotzdem nicht! (Das ist unglaublich, aber trotzdem, siehe die Codes unten :)
while-Schleife:
<!DOCTYPE html> <script> var Continue = "no"; setTimeout(function(){Continue = "yes";}, 5000); //after 5 seconds, "Continue" is changed to "yes" while(Continue === 'no'){}; //"while" loop will stop when "Continue" is changed to "yes" 5 seconds later //the problem here is that "while" loop prevents the "setTimeout()" to change "Continue" to "yes" 5 seconds later //worse, the "while" loop will freeze the entire browser for a brief time until you click the "stop" script execution button </script>
Rekursion:
<!DOCTYPE html> 1234 <script> function Wait_If(v,c){ if (window[v] === c){Wait_If(v,c)}; }; Continue_Code = "no" setTimeout(function(){Continue_Code = "yes";}, 5000); //after 5 seconds, "Continue_Code" is changed to "yes" Wait_If('Continue_Code', 'no'); //the problem here, the javascript console trows the "too much recursion" error, because "Wait_If()" function calls itself repeatedly! document.write('<br>5678'); //this line will not be executed because of the "too much recursion" error above! </script>
quelle
Nein, Sie müssten Ihre eigene Lösung erstellen. Wie mit dem Observer-Designmuster oder so.
Wenn Sie keine Kontrolle über die Variable haben oder wer sie verwendet, sind Sie leider zum Scheitern verurteilt. EDIT: Oder verwenden Sie Skilldricks Lösung!
Mike
quelle