Подтвердить что ты не робот

Как я могу заставить программу ждать изменения переменной в javascript?

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

4b9b3361

Ответ 1

Редактировать 2018: Пожалуйста, посмотрите на Объекты getterters и setters и 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();

Ответ 2

Устные переводчики 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>

Ответ 3

Я бы рекомендовал обертку, которая будет обрабатывать измененное значение. Например, вы можете иметь функцию 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/

Ответ 4

Вы можете использовать свойства:

Документация MDD Object.defineProperty

Пример:

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

Ответ 5

Вопрос был опубликован давным-давно, многие ответы периодически объединяют цели и приводят к ненужным тратам ресурсов, если цель не изменяется. Кроме того, большинство ответов не блокируют программу во время ожидания изменений, как того требует исходное сообщение.

Теперь мы можем применить решение, основанное исключительно на событиях.

В решении используется событие 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>

Ответ 6

Супер устаревший, но, безусловно, хорошие способы приспособить это. Просто написал это для проекта и решил, что я поделюсь. Как и некоторые другие, разнообразны по стилю.

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;

Ответ 7

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>

Ответ 8

В качестве альтернативы вы можете создать функцию, которая выполняет задачи, основываясь на значении ее "статических" переменных, например ниже:

enter image description here

<!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>

Ответ 9

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

Если у вас нет контроля над переменной или кто ее использует, я боюсь, что вы обречены. EDIT: Или используйте решение Skilldrick!

Mike