Window.scrollTo с setTimeout переходит в бесконечный цикл, но отлично работает без setTimeout

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

while(document.documentElement.scrollTop <= document.body.scrollHeight-500){
     window.scrollTo(0, document.documentElement.scrollTop+500);
}

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

while (document.documentElement.scrollTop <= document.body.scrollHeight - 500) {
setTimeout(
    function() {
        window.scrollTo(0, document.documentElement.scrollTop + 500);
    }, 300);
}

Теперь это заканчивается бесконечным циклом, как я предполагаю, из-за асинхронного выпрыгивания из while.

Как изменить приведенный выше скрипт, чтобы он медленно прокручивался вниз, чтобы он загружал все? Или просто заставить страницу загрузить все каким-то другим способом

Цикл while блокирует выполнение, и функция timed никогда не выполняется.

Teemu 14.05.2019 09:10
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
1
934
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Один из вариантов — поместить его в функцию async и await промис, который разрешается через 300 мс внутри while:

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
(async () => {
  while (document.documentElement.scrollTop <= document.body.scrollHeight - 500) {
    window.scrollTo(0, document.documentElement.scrollTop + 500);
    await delay(300);
  }
})();

setTimeout(func, n) очереди func для вызова (минимум) н мс.

поэтому ваш второй подход в основном

while (document.documentElement.scrollTop <= document.body.scrollHeight - 500) {
  addAnotherTimeout();
}

Код внутри цикла не влияет на состояние цикла, поэтому здесь получается бесконечный цикл.

Здесь рекурсивная версия (вроде):

var scrollTimeout;
function scrollElement(){
    clearTimeout(scrollTimeout);
    if (document.documentElement.scrollTop <= document.body.scrollHeight-500){
        window.scrollTo(0, document.documentElement.scrollTop+500);
        scrollTimeout = setTimeout(scrollElement, 300);
    }
}

// start the scrolling:
scrollElement();

Часть с clearTimeout() в начале scrollElement() не требуется для самого цикла/рекурсии, но для предотвращения нескольких одновременных циклов.

Если вы начинаете второй цикл, а предыдущий еще не закончен, уничтожьте предыдущий.

"n всегда будет >= 10 мс" Хм... нет. Существует дроссель 4 мс, но он эффективен только тогда, когда уровень вложенности обратных вызовов превышает глубину 5 уровней. Шаги инициализации таймера • 11. Исторически этот дроссель действительно был установлен в некоторых браузерах на 10 мс, но это уже было только после некоторых уровней вложенности. Однако это не меняет того факта, что это действительно всегда будет срабатывать, по крайней мере, в следующем цикле событий.
Kaiido 14.05.2019 10:24

Другие вопросы по теме