프로그램이 자바 스크립트의 변수 변경을 기다리도록하려면 어떻게해야합니까?
JavaScript 프로그램이 변수가 변경 될 때까지 특정 실행 지점에서 기다리도록 강제하고 싶습니다. 그것을 할 방법이 있습니까? 이미 이벤트가 발생할 때까지 프로그램이 대기하도록하는 "내러티브 JavaScript"라는 확장을 찾았습니다. 예를 들어 onclick 이벤트처럼 작동하는 "변수 변경 이벤트"와 같은 새 이벤트를 만드는 방법이 있습니까?
2018 편집 : Object getter 및 setter 및 Proxies를 살펴보십시오 . 아래의 이전 답변 :
빠르고 쉬운 솔루션은 다음과 같습니다.
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();
JavaScript 인터프리터는 단일 스레드이므로 코드가 변수를 변경하지 않는 다른 코드에서 대기 중일 때 변수를 변경할 수 없습니다.
제 생각에는 getter 및 setter 기능을 가진 어떤 종류의 객체에 변수를 래핑하는 것이 가장 좋은 솔루션이 될 것입니다. 그런 다음 객체의 setter 함수가 호출 될 때 호출되는 객체에 콜백 함수를 등록 할 수 있습니다. 그런 다음 콜백에서 getter 함수를 사용하여 현재 값을 검색 할 수 있습니다.
function Wrapper(callback) {
var value;
this.set = function(v) {
value = v;
callback(this);
}
this.get = function() {
return value;
}
}
다음과 같이 쉽게 사용할 수 있습니다.
<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>
변경되는 값을 처리 할 래퍼를 권장합니다. 예를 들어 다음과 같은 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();
}
}
그런 다음 모니터링하려는 값을 보유 할 객체를 만들 수 있으며 값이 변경 될 때 호출 될 함수도 만들 수 있습니다. 예를 들어 값이 변경되고 초기 값이 10 일 때 경고를 받으려면 다음과 같은 코드를 작성합니다.
var myVar = new Variable(10, function(){alert("Value changed!");});
를 function(){alert("Value changed!");}
호출하면 핸들러 가 호출됩니다 (코드를 보면) SetValue()
.
다음과 같이 가치를 얻을 수 있습니다.
alert(myVar.GetValue());
다음과 같이 값을 설정할 수 있습니다.
myVar.SetValue(12);
그리고 즉시 화면에 경고가 표시됩니다. 작동 방식보기 : http://jsfiddle.net/cDJsB/
속성 을 사용할 수 있습니다 .
예:
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
이 질문은 오래 전에 게시되었으며 많은 답변이 정기적으로 대상을 모으고 대상이 변경되지 않으면 불필요한 자원 낭비를 초래합니다. 또한 대부분의 답변은 원래 게시물에서 요구하는 변경 사항을 기다리는 동안 프로그램을 차단하지 않습니다.
이제 순전히 이벤트 기반 솔루션을 적용 할 수 있습니다.
이 솔루션은 onClick 이벤트를 사용하여 값 변경으로 트리거 된 이벤트를 전달합니다.
이 솔루션은 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>
아주 오래되었지만 확실히 이것을 수용하는 좋은 방법. 프로젝트를 위해 이것을 작성하고 내가 공유 할 것이라고 생각했습니다. 다른 일부와 유사하며 스타일이 다양합니다.
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;
JavaScript는 최악의 프로그램 / 스크립팅 언어 중 하나입니다!
"기다려"는 JavaScript에서 불가능한 것 같습니다! (예, 실제 생활과 마찬가지로 때로는 기다리는 것이 최선의 선택입니다!)
"while"루프와 "Recursion"(함수는 ...까지 반복적으로 호출)을 시도했지만 JavaScript는 어쨌든 작동을 거부합니다! (이것은 믿을 수 없지만 어쨌든 아래 코드를 참조하십시오.)
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>
재귀 :
<!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>
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>
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.
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();
};
};
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!
Mike
'Programing' 카테고리의 다른 글
테이블을 다른 파일 그룹으로 이동하려면 어떻게해야합니까? (0) | 2020.12.08 |
---|---|
jQuery size () 메서드 대 길이 속성 (0) | 2020.12.08 |
.S 파일이란 무엇입니까? (0) | 2020.12.08 |
Jenkins와 Maven의 차이점 (0) | 2020.12.08 |
ARC 아래의 NSString 속성은 강력해야합니까 아니면 복사해야합니까? (0) | 2020.12.08 |