如何在 JS 的 setInterval 中等待?

新手上路,请多包涵

我有一个看起来像这样的代码段:

 async function autoScroll(page, maxDate = null) {
  await page.evaluate(async () => {
    await new Promise(async (resolve, reject) => {
        try {
            const scrollHeight = document.body.scrollHeight;
            let lastScrollTop = 0;

            const interval = setInterval(async () => {
                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())) {
                    clearInterval(interval);
                    resolve();
                } else {
                    lastScrollTop = scrollTop;
                }
            }, 2000);
        } catch (err) {
            console.error(err);
            reject(err.toString());
        }
    });
});
}

其中 extractDate 方法具有以下形式:

 function extractDate(html) {
    return new Promise((resolve, reject) => {
        // Rest removed for brevity.
        resolve(result);
    });
}

现在的问题是,我的代码一直在滚动,但它不会等待里面的其他东西 setInterval 完成,因为它每 2 秒滚动一次,但通常 extractDate 函数应该超过 2 秒,所以我实际上想等待内部的所有内容 setInterval 在调用新间隔之前完成。

由于东西的异步性质,我没有设法 console.log 东西,所以请看代码的行为。

那么,我如何确保 setInterval 中的所有内容在进行下一次间隔调用之前完成?

编辑:

此解决方案使用 setTimeout 仅滚动一次并使用 puppeteer 抛出未处理的承诺拒绝错误。

  async function autoScroll(page, maxDate = null) {
     await page.evaluate(async () => {
        await new Promise(async (resolve, reject) => {
            try {
               const scrollHeight = document.body.scrollHeight;
               let lastScrollTop = 0;

                const interval = async function() {
                    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())) {
                        resolve();
                    } else {
                        lastScrollTop = scrollTop;
                        setTimeout(interval, 2000);
                    }
                }

                setTimeout(interval, 2000);

            } catch (err) {
                console.error(err);
                reject(err.toString());
            }
        });
    });
}

原文由 tinker 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 922
2 个回答

将间隔函数改为 _递归 setTimeout 函数_,这样您就可以在函数完成后为下一次迭代初始化超时。

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

原文由 CertainPerformance 发布,翻译遵循 CC BY-SA 4.0 许可协议

使用以下代码:

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

原文由 ziishaned 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题