如何让程序等待 javascript 中的变量更改?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3635924/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I make a program wait for a variable change in javascript?
提问by Thanasis Petsas
I want to force a JavaScript program to wait in some particular points of its execution until a variable has changed. Is there a way to do it? I have already found an extension that is called "narrative JavaScript" that force the program to wait until an event to happen. Is there a way to create a new event, a "variable change event" for example that behaves like onclick event..
我想强制 JavaScript 程序在其执行的某些特定点等待,直到变量发生更改。有没有办法做到这一点?我已经找到了一个名为“narrative JavaScript”的扩展,它强制程序等待事件发生。有没有办法创建一个新事件,例如一个“变量更改事件”,其行为类似于 onclick 事件..
回答by aularon
Edit 2018: Please look into Object getters and settersand Proxies. Old answer below:
2018 年编辑:请查看Object getter 和 setter以及Proxies。下面的旧答案:
a quick and easy solution goes like this:
一个快速简单的解决方案是这样的:
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();
回答by Reboot
JavaScript interpreters are single threaded, so a variable can never change, when the code is waiting in some other code that does not change the variable.
JavaScript 解释器是单线程的,所以当代码在其他不改变变量的代码中等待时,变量永远不会改变。
In my opinion it would be the best solution to wrap the variable in some kind of object that has a getter and setter function. You can then register a callback function in the object that is called when the setter function of the object is called. You can then use the getter function in the callback to retrieve the current value:
在我看来,将变量包装在某种具有 getter 和 setter 函数的对象中将是最好的解决方案。然后可以在调用对象的 setter 函数时调用的对象中注册回调函数。然后您可以在回调中使用 getter 函数来检索当前值:
function Wrapper(callback) {
var value;
this.set = function(v) {
value = v;
callback(this);
}
this.get = function() {
return value;
}
}
This could be easily used like this:
这可以像这样轻松使用:
<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>
回答by Cipi
I would recommend a wrapper that will handle value being changed. For example you can have JavaScript function, like this:
我会推荐一个包装器来处理被改变的值。例如,您可以拥有 JavaScript 函数,如下所示:
?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();
}
}
And then you can make an object out of it that will hold value that you want to monitor, and also a function that will be called when the value gets changed. For example, if you want to be alerted when the value changes, and initial value is 10, you would write code like this:
然后您可以从中创建一个对象,该对象将保存您想要监视的值,以及一个将在值更改时调用的函数。例如,如果您想在值更改时收到警报,并且初始值为 10,您可以编写如下代码:
var myVar = new Variable(10, function(){alert("Value changed!");});
Handler function(){alert("Value changed!");}will be called (if you look at the code) when SetValue()is called.
Handlerfunction(){alert("Value changed!");}将在被调用时被调用(如果您查看代码)SetValue()。
You can get value like so:
你可以获得这样的价值:
alert(myVar.GetValue());
You can set value like so:
您可以像这样设置值:
myVar.SetValue(12);
And immediately after, an alert will be shown on the screen. See how it works: http://jsfiddle.net/cDJsB/
紧接着,屏幕上将显示警报。看看它是如何工作的:http: //jsfiddle.net/cDJsB/
回答by Homer Liu
The question was posted long time ago, many answers pool the target periodically and produces unnecessary waste of resources if the target is unchanged. In addition, most answers do not block the program while waiting for changes as required by the original post.
这个问题很久以前就贴出来了,很多答案会周期性地汇集目标,如果目标不变,就会产生不必要的资源浪费。此外,大多数答案在等待原始帖子要求的更改时不会阻止程序。
We can now apply a solution that is purely event-driven.
我们现在可以应用纯事件驱动的解决方案。
The solution uses onClick event to deliver event triggered by value change.
该解决方案使用 onClick 事件来传递由值更改触发的事件。
The solution can be run on modern browsers that support Promise and async/await. If you are using Node.js, consider EventEmitteras a better solution.
该解决方案可以在支持 Promise 和 async/await 的现代浏览器上运行。如果您使用 Node.js,请考虑将EventEmitter作为更好的解决方案。
<!-- 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>
回答by User
JavaScript is one of the worst program\scripting language ever!
JavaScript 是有史以来最糟糕的程序\脚本语言之一!
"Wait" seems to be impossible in JavaScript! (Yes, like in the real life, sometimes waiting is the best option!)
“等待”在 JavaScript 中似乎是不可能的!(是的,就像在现实生活中一样,有时等待是最好的选择!)
I tried "while" loop and "Recursion" (a function calls itself repeatedly until ...), but JavaScript refuses to work anyway! (This is unbelievable, but anyway, see the codes below:)
我尝试了“while”循环和“递归”(一个函数反复调用自己直到......),但JavaScript无论如何都拒绝工作!(这令人难以置信,但无论如何,请参阅下面的代码:)
while loop:
while循环:
<!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>
Recursion:
递归:
<!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>
回答by Eduardo Cuomo
You can use properties:
您可以使用属性:
Object.defineProperty MDN documentation
Example:
例子:
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
回答by darcher
Super dated, but certainly good ways to accomodate this. Just wrote this up for a project and figured I'd share. Similar to some of the others, varied in style.
超级过时,但肯定是适应这一点的好方法。刚刚为一个项目写了这个,并认为我会分享。与其他一些类似,风格各异。
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;
回答by User
Alternatively, you can make a function that executes tasks based on the value of its "Static" variables, example below:
或者,您可以创建一个函数,根据其“静态”变量的值执行任务,示例如下:
<!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>
回答by JakeJ
What worked for me (I looked all over the place and ended up using someone's jsfiddler / very slightly modifying it - worked nicely) was to set that variable to an object with a getter and setter, and the setter triggers the function that is waiting for variable change.
对我有用的(我四处查看并最终使用了某人的 jsfiddler / 对其进行了很小的修改 - 效果很好)是将该变量设置为具有 getter 和 setter 的对象,并且 setter 触发正在等待的函数变量变化。
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();
};
};
回答by Mike Gleason jr Couturier
No you would have to create your own solution. Like using the Observer design pattern or something.
不,您必须创建自己的解决方案。比如使用观察者设计模式什么的。
If you have no control over the variable or who is using it, I'm afraid you're doomed. EDIT: Or use Skilldrick's solution!
如果你无法控制变量或谁在使用它,恐怕你就完蛋了。编辑:或使用 Skilldrick 的解决方案!
Mike
麦克风


