How to await inside setInterval in JS?

Turn the interval function into a recursive setTimeout function instead, that way you can initialize a timeout for the next iteration once the function has finished.

async function doScroll() {
  window.scrollBy(0, scrollHeight);
  const scrollTop = document.documentElement.scrollTop;
  let lastDate = null;
  if (maxDate) {
    const html = new XMLSerializer().serializeToString(document.doctype) + document.documentElement.outerHTML;
    await extractDate(html).then((date) => {
      lastDate = date;
    });
  }
  if (scrollTop === lastScrollTop ||
      (maxDate && lastDate && maxDate.getTime() >= lastDate.getTime())) {
    // No need to `clearInterval`:
    resolve();
  } else {
    lastScrollTop = scrollTop;
    // Recursive setTimeout:
    setTimeout(doScroll, 2000); // <------------------
  }
}
setTimeout(doScroll, 2000);

I generally opt for this solution. I think it's cleaner:

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

async function loop() {
  while (/* condition */) {
    /* code to wait on goes here (sync or async) */    

    await delay(100)
  }
}

Your loop function will return a promise. You can wait for it to stop looping, or you can discard it.


Use the following code:

setInterval(async () => {
    await fetch("https://www.google.com/") 
}, 100);