承诺中的setTimeout-如何解决以及为何仅运行一次?

时间:2019-04-13 16:20:19

标签: javascript node.js recursion promise es6-promise

我想基于Promise中的setTimeout模拟基于随机时间的鼠标滚动。 我的目标是继续向下滚动到网页的底部:应重复调用autoScroll函数,直到到达底部为止,然后解决Promise。 目前,该代码仅运行一次,然后出现2​​个错误: 未捕获的ReferenceError:未定义loopScroll(在浏览器的控制台中) UnhandledPromiseRejectionWarning(在VSCode中)。

async function loopScroll(page) { 
    await page.evaluate(async () => {
        await new Promise((resolve, reject) => {
            let rand = Math.round(Math.random() * (3000 - 500)) + 500;
            setTimeout(function () {
                function autoScroll() {
                    let scrollHeight = document.body.scrollHeight;
                    let currentHeight = 0;
                    let distance = 100;
                    window.scrollBy(0, distance);
                    currentHeight += distance;
                    if (currentHeight >= scrollHeight) {
                        resolve();
                    }
                }
                autoScroll();
                loopScroll(page);
            }, rand);
        });
    });
};

这个异步-承诺的事情让我有些困惑,我对他们没有太多的经验,所以我真的不知道我在做什么错。 预先感谢。

1 个答案:

答案 0 :(得分:1)

如评论中所述,这里的第一个问题是这部分代码在NodeJS环境中运行:

 async function loopScroll(page) { 
   await page.evaluate(/* page environment */);
 }

并且在loopScroll被定义的地方,页面环境无法访问该功能。这就是为什么调用loopScroll失败并结束执行的原因。

因为您已经在使用async / await,所以根本不需要使用递归,只需循环await

 await page.evaluate(async () => {
  const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

  let scrollHeight = document.body.scrollHeight;
  let currentHeight = 0;
  let distance = 100;

  while(true) {
    let rand = Math.round(Math.random() * (3000 - 500)) + 500;

    window.scrollBy(0, distance);
    currentHeight += distance;
    if (currentHeight >= scrollHeight) {
         break;
    }

   await delay(rand);
 }
});