2010-09-03 7 views
45

Я хочу заставить программу JavaScript ждать в некоторых точках ее выполнения до тех пор, пока переменная не изменится. Есть ли способ сделать это? Я уже нашел расширение, которое называется «описательный JavaScript», заставляющее программу ждать, пока событие не произойдет. Есть ли способ создать новое событие - событие с переменным изменением, например, которое ведет себя как событие onclick.Как я могу заставить программу ждать изменения переменной в javascript?

ответ

0

Нет, вам не придется создавать собственное решение. Как и с использованием шаблона проектирования Observer или чего-то еще.

Если у вас нет контроля над переменной или кто ее использует, я боюсь, что вы обречены. EDIT: Или используйте решение 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

отредактированный сейчас, он проверяет каждые 50 мс и работает для non-bools.это, как я сказал, быстрый и простой способ сделать это, перейдите по этой ссылке: http://stackoverflow.com/questions/1029241/javascript-object-watch-for-all-browsers (уже добавлено @mplungjan) для более углубленное решение проблем. – aularon

+0

Я думаю, вы имели в виду 'something === something_cachedValue'. Затем он работает: http://jsfiddle.net/pEnYC/ – Skilldrick

+0

@Skilldrick, да, я имел в виду это, я исправил его. Спасибо за исправление:) – aularon

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!");}); 

Handler function(){alert("Value changed!");} будет называться (если вы посмотрите на код), когда SetValue() является называется.

Вы можете получить значение следующим образом:

alert(myVar.GetValue()); 

Вы можете установить значение следующим образом:

myVar.SetValue(12); 

И сразу же после этого, предупреждение будет отображаться на экране. Посмотрите, как это работает: http://jsfiddle.net/cDJsB/

+0

Спасибо за ответ, но это не совсем то, что я хочу. Посмотрите мой комментарий на aularon, пожалуйста! –

15

Условные обозначения для JavaScript однопоточные, поэтому переменная не может меняться, когда код ожидает в каком-то другом коде, который не меняет эту переменную.

По моему мнению, было бы лучшим решением для переноса переменной в объект какого-либо объекта, который имеет функцию getter и setter. Затем вы можете зарегистрировать функцию обратного вызова в объекте, который вызывается при вызове функции setter объекта. После этого вы можете использовать функцию геттер в функции обратного вызова для получения текущего значения:

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

+0

Спасибо за ответ, но это не совсем то, что я хочу. Посмотрите мой комментарий на aularon, пожалуйста! –

+1

Как я уже говорил, интерпретаторы JavaScript однопоточные. Вы не можете заблокировать поток и заставить его ждать, пока какой-нибудь другой поток изменит переменную, потому что нет другого потока, который может изменить переменную. Обработчик событий JavaScript не может выполняться, а другой уже выполняется. – Reboot

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 
Смежные вопросы