简体   繁体   中英

window.scrollTo with setTimeout goes into infinite loop but works fine without setTimeout

I am writing a script that would scroll down the page to load it completely for further processing, with following very basic function, scroll jumps to the bottom but it fails to load everything in between

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

so I have modified it with setTimeout so it would scroll it more slowly and give time for the page to load its stuff.

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

Now it ends in an infinite loop, I am assuming due to async jumping out of while somehow.

How do I modify the above script to scroll it down slowly so it would load everything? Or just force the page to load everything in some other way

setTimeout(func, n) queues func to be caled in (at least) n ms.

so your second approach is basically

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

The code inside the loop has no influence to the condition of the loop, that's why you get an infinite loop here.

Here a recursive version (kind of):

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();

The part with the clearTimeout() at the beginning of the scrollElement() is not required for the loop/recursion itself, but to prevent multiple concurrent loops.

If you start a second loop and the previous one isn't finished yet, kill the previous one.

One option is to put it into an async function, and await a Promise that resolves after 300ms inside the 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);
  }
})();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM