-1

Мне нужно сделать функцию, которая будет ждать, пока пользователь нажмёт кнопку, а потом возвращать результат. Я пробовал так:

let state = {"ready": false};
function getValue() {
    state.ready = false;
    document.getElementById("form").style.display="block";
    while(!state.ready) {}
    return document.getElementById("val").value;
}
function setReady() {state.ready = true}
<html>
<head>
</head>
<body>
<div id="form" style="display: none;">
<input id="val">
<button onclick="setReady();">OK</button>
</div>
<button onclick="alert(getValue());">Run</button>
</body>
</html>

Но браузер говорит, что страница зависла. Есть другой способ это сделать?

Vad Sim
  • 235
  • 2
    Возможно, стоить начать с некоторых базовых вещей, так что может пригодится. Почему блокируется страница в вашем случае и как можно схитрить: https://learn.javascript.ru/event-loop Основы асинхронности и возможных решений вашего задания: https://learn.javascript.ru/async – vsemozhebuty Jul 18 '21 at 11:32

2 Answers2

2

Попробуйте обработчик событий:

<button>Run</button>
<script>
  var button = document.querySelector("button");
  button.addEventListener("click", function() {
    alert("Кнопка нажата.");
  });
</script>
Elusha
  • 823
  • Не подходит, эту функцию будет использовать другой код – Vad Sim Jul 18 '21 at 10:59
0

Решение через Proxy (для наблюдения за значением) и Promise (для "подождать"):

const observe = (obj, cfg) => new Proxy(obj, {
  set(target, prop, value) {
    if (cfg.hasOwnProperty(prop) && cfg[prop].when(value))
      cfg[prop].do(value); 
    target[prop] = value; 
    return true; 
  }, 
});
const stateData = { ready: false }, 
      stateObsCfg = {}, 
      state = observe(stateData, stateObsCfg);

function getValue() { state.ready = false;  const form = document.getElementById('form'); form.style.display = '';  return new Promise(resolve => {    stateObsCfg.ready = {     when: v => v,      do: () => {        const inp = document.getElementById('val'); form.style.display = 'none';        resolve(inp.value);        inp.value = '';        delete stateObsCfg.ready;      },   };  }); }

function setReady(value) {  state.ready = Boolean(value); }

<div id="form" style="display: none;">
  <input id="val">
  <button onclick="setReady(true);">OK</button>
</div>
<button onclick="getValue().then(alert);">Run</button>

В объекте конфигурации наблюдателя stateObsCfg, свойство when предполагает коллбэк для вычисления условий, а свойство do - коллбэк действий (выполняемых если вызов when вернул истинное значение).
Динамическое изменение конфига возможно благодаря тому, что объекты в JS передаются по ссылке (референсу).

yar85
  • 10,940