2010-09-03 70 views
45

我想強制JavaScript程序在其執行的某些特定點上等待,直到變量發生變化。有沒有辦法做到這一點?我已經找到了一個名爲「敘述性JavaScript」的擴展,強制程序等待事件發生。有沒有辦法創建一個新的事件,例如「可變更改事件」,就像onclick事件一樣。如何讓程序等待javascript中的變量更改?

回答

0

不,您將不得不創建自己的解決方案。就像使用Observer設計模式或其他東西一樣。

如果你無法控制變量或者誰正在使用它,恐怕你註定了。 編輯:或使用Skilldrick的解決方案!

邁克

76

一個快速簡便的解決方案是這樣的:

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(); 
+1

現在編輯,它每50ms檢查一次,並適用於非布爾。正如我所說的那樣快捷簡單,請點擊此鏈接:http://stackoverflow.com/questions/1029241/javascript-object-watch-for-all-browsers(已由@mplungjan發佈)瞭解更多信息深入解決問題的解決方案。 – aularon 2010-09-03 13:37:45

+0

我認爲你的意思是'something === something_cachedValue'。然後,它的工作原理:http://jsfiddle.net/pEnYC/ – Skilldrick 2010-09-03 13:45:31

+0

@Skilldrick,是的,我的意思是,我修正了它。感謝您的更正:) – aularon 2010-09-03 13:48:20

5

我會建議的包裝,將處理被改變的值。例如,你可以有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/

+0

謝謝你的答案,但它不完全是我想要的。請看我對aularon的評論! – 2010-09-09 12:16:38

15

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

可能是最好的解決方案,如果你有控制原始變量。 – Skilldrick 2010-09-03 13:58:00

+0

謝謝你的回答,但這不完全是我想要的。請看我對aularon的評論! – 2010-09-09 12:16:04

+1

正如我所解釋的,JavaScript解釋器是單線程的。你不能阻塞線程,並等待其他線程去改變一個變量,因爲沒有其他的線程可以改變一個變量。當另一個正在執行時,不能執行JavaScript事件處理程序。 – Reboot 2010-09-10 22:42:00

1

您可以使用性能

Object.defineProperty MDN documentation

示例:

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