ожидание в цикле while изменения внешней переменной или события?

#javascript #node.js

#javascript #node.js

Вопрос:

У меня вопрос / проблема с циклом whileloop

Мне нужно подождать, пока что-то не изменится за пределами цикла while.

Допустим, у меня есть этот цикл while:

 window.changeMe = true;
while(window.changeMe){

}
  

теперь у меня есть эти два варианта:

  1. Измените changeMe переменную с помощью консоли / выполнения JavaScript
  2. Измените changeMe переменную с помощью события WebSocket

но ни то, ни другое не работает, если я изменяю переменную напрямую, она не изменяется. Если я запускаю событие WebSocket, оно не вызывается. Может BLOCKED быть, это .. так есть ли другой способ изменить переменную?

Я знал, что могу использовать await , и это уже работает таким образом, но проблема в том, что эти функции с while вызываются через аддон, и использование многих await выглядит довольно уродливо для создателя аддона: (

система с setTimeout amp; обратными вызовами также работает, но также выглядит довольно уродливо..

Комментарии:

1. Вы не можете использовать цикл while. Это заблокирует браузер. Обычно вы используете интервал. В идеале вы запускаете событие…

2. Если вам нужно выполнить опрос в цикле, то вам придется использовать await с небольшими задержками. Не уверен, чего еще вы ожидаете.

3. Вы не можете. Javascript является однократным, и синхронная задача никогда не прерывается. Таким образом, как только ваш код попадает в while цикл, он никогда не прерывается, и никакой другой код не может выполняться. Читайте о модели параллелизма JS и eventloop здесь developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

4. @epascarello о да, извините, это тоже работает в данный момент, но вызов всех функций с обратным вызовом также выглядит довольно уродливо xD

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

Ответ №1:

Да, вы правы. Наличие бесконечного цикла while предотвратит выполнение любого другого кода из цикла событий javascript, который занимает основной поток.

Чтобы имитировать такое же поведение, вы можете реализовать свой собственный цикл while, который подходит для асинхронных событий и выполнения внешнего кода. Вы должны использовать:

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

ПРИМЕР:

 window.changeMe = true;

let stop = setTimeout(() => { console.log("External change stop"); window.changeMe = false; }, 4000)

var whileLoop = () => {

  console.log("Inside: ", window.changeMe)
  
  return window.changeMe
    ? setTimeout(() => { whileLoop(); }, 0)
    : false

}

whileLoop()

console.log("Outside: ", window.changeMe)
  

Вот скрипка:
https://jsfiddle.net/qwmosfrd /

Вот скрипка setInterval: https://jsfiddle.net/2s6pa1jo /

Пример скрипки с обещанием возвращаемого значения: https://jsfiddle.net/0qum6gnf /

Комментарии:

1. спасибо за скрипку, но проблема здесь будет в том, что мне нужно вызвать stop Outside , чтобы он вернулся к той же проблеме, для получения дополнительных разъяснений я вызываю «NativeFunctions» вне браузера, и мне нужно знать в Js, когда это будет сделано. С тайм-аутом я уже пробовал это, и его работа мне известна. но как написано в комментариях выше. вызов функций со многими обратными вызовами также выглядит довольно некрасиво.. извините, забыл это написать в сообщении..

2. Таким образом, вы можете изменить это на setInterval с таймаутом 0. Вы должны понимать, что каждый из этих вызовов функций является отдельной сущностью в основном потоке, позволяющей вам выполнять другие действия в вашем коде. Добавлена скрипка setInterval, которая очищает себя.

3. хм, да, но допустим, вы whileLoop() возвращаете значение? var returnValue = whileLoop() .. в этом случае это не будет работать правильно? потому что setTimeout или setInterval покинут вашу функцию whileLoop и не вернут что-либо

4. ДА. В этом случае вы должны использовать обещание. Посмотрите. Вы пытаетесь бороться с архитектурой javascript. Это не java или c . Добавлена третья скрипка.

5. да, я знал xD .. о работе с then чем-то, о чем я не думал .. я думаю, что это лучшее решение между ожиданием и обратными вызовами (это то же самое, что и обратные вызовы, но выглядит более дружественным к Js;)

Ответ №2:

JavaScript является однопоточным. Если у вас есть while (true) {} , то ничто другое вне while цикла не может изменить состояние вашей программы. Вам нужно изменить свой подход. Вероятно, вы хотите вместо этого настроить прослушиватели событий или поместить это в async функцию, чтобы вы могли использовать await для освобождения выполнения, или какой-либо другой асинхронный API. Но обычная ваниль while () {} синхронна и не может быть затронута другими вещами во время ее выполнения.

Ответ №3:

Вы не можете использовать while цикл таким образом в nodejs.

Nodejs запускает ваш Javascript в одном потоке, а общая архитектура среды управляется событиями. То, что делает ваш while цикл, — это цикл вращения, поэтому, пока этот цикл выполняется, никакие другие события никогда не могут выполняться. Вы должны вернуть управление обратно в цикл событий, прежде чем смогут выполняться какие-либо другие события. Это означает, что таймеры, сетевые события и т. Д. … Не могут выполняться во время выполнения цикла вращения. Итак, в nodejs это никогда не правильный способ написания кода. Это не сработает.

Единственным исключением может быть await , если внутри цикла есть что-то, что приостанавливает цикл и позволяет запускать другие события.

Итак, пока это выполняется:

 while(window.changeMe){

}
  

Никакие другие события не могут выполняться, и, следовательно, ничто другое не получает возможности изменить changeMe свойство. Таким образом, это просто бесконечный цикл, который никогда не может завершиться, и больше ничего не может быть запущено.

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

Комментарии:

1. да, я уже знаю, что ty, и часть события не будет работать, потому что я получаю уведомления только за пределами js (через WebSocket или прямое выполнение JavaScript, например, консоль)

2. @DetoxJS — Итак, если вы уже знаете это, тогда в чем ваш вопрос? Вы не можете сделать это таким образом. Вы должны спроектировать его по-другому, чтобы использовать механизм, управляемый событиями.

3. idn может быть, есть способ получать сообщения webhook с помощью функций, не ожидающих события

4. @DetoxJS — Нет. Все сообщения проходят через цикл событий, и ваш while цикл блокирует цикл событий.