Как заставить JavaScript записывать результат с течением времени (не мгновенно)?

#javascript

#javascript

Вопрос:

У меня есть программа, которая записывает множество результатов if. Например, это:

 const a = prompt();
for(let i = 1; i < a; i   ) {
  console.log(i);
}
 

(не фактический код)
Итак, когда вы вводите большое число, появляется тонна ответов, ожидающих ввода в консоль. Итак, когда он достигает некоторой точки, встроенный компилятор браузера (Opera GX) просто перестает работать. Надеюсь, мне нужен какой-то способ записать эти числа сразу после вычисления, не теряя времени. Как я могу это сделать?
(просто чтобы вы знали, мой фактический код помещает результаты в элемент «div»)

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

1. «встроенный компилятор просто перестает работать» Вы должны уточнить это.

2. В чем разница между мгновенно и немедленно? В заголовке: «Как заставить JavaScript записывать результат с течением времени (не мгновенно)?» и в описании: «Мне нужен какой-то способ немедленно записать эти числа»

3. Мгновенно означает «сохранение этих значений для печати после завершения программы». Немедленно означает «Я вычислил это число. Я должен поместить его в консоль и начать вычислять другой «. Точно так же, как в Python (но, надеюсь, намного быстрее)

4. Вы могли бы попробовать рекурсивный setTimeout . Это разобьет один долго работающий код на множество небольших фрагментов, управляемых циклом событий. Что-то вроде let i = 0; setTimeout(function f() { i; console.log(i); if (i < a) setTimeout(f, 0); }, 0);

5. Вы обращались к сервисным работникам? developers.google.com/web/fundamentals/primers/service-workers

Ответ №1:

JavaScript является однопоточным. Это означает, что во время выполнения вашего цикла события не могут быть обработаны, и страница не отвечает. Вы могли бы использовать «рекурсивный» setTimeout . Это разобьет один долго выполняющийся код на множество небольших фрагментов, управляемых циклом событий.

 const a = prompt();
const container = document.getElementById('container');
const f = (() => {
  let i = 0;
  return () => {
    for (let j = 0; j < 1e9;   j) {} // simulates long calculation 
      i;
    console.log(i);
    container.innerText  = ' '   i;
    if (i < a) setTimeout(f, 0);
  };
})();
setTimeout(f, 0); 
 <div id="container"></div> 

Это не настоящий рекурсивный вызов, и он не создаст большой стек вызовов. setTimeout(f, 0) помещает событие в цикл событий, который почти сразу же удаляется и обрабатывается.

Я использовал закрытие только для того, чтобы избежать глобального счетчика i . Более простая, но менее чистая версия

 const a = prompt();
const container = document.getElementById('container');
let i = 0;
function f() {
  for (let j = 0; j < 1e9;   j) {} // simulates long calculation 
    i;
  console.log(i);
  container.innerText  = ' '   i;
  if (i < a) setTimeout(f, 0);
};
setTimeout(f, 0); 
 <div id="container"></div> 

Помните, что страница по-прежнему не реагирует во время циклов (длительное вычисление), но теперь у вас есть много более коротких циклов вместо одного длительного цикла, а события обрабатываются между двумя циклами.