Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/412.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在JS中如何在setInterval内等待?_Javascript_Asynchronous_Promise_Async Await_Puppeteer - Fatal编程技术网

Javascript 在JS中如何在setInterval内等待?

Javascript 在JS中如何在setInterval内等待?,javascript,asynchronous,promise,async-await,puppeteer,Javascript,Asynchronous,Promise,Async Await,Puppeteer,我有一个代码段如下所示: async function autoScroll(page, maxDate = null) { await page.evaluate(async () => { await new Promise(async (resolve, reject) => { try { const scrollHeight = document.body.scrollHeight; let las

我有一个代码段如下所示:

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
中的所有内容完成,然后再调用新的interval

由于stuff的异步特性,我没有设法
console.log
stuff,因此无法查看代码的行为

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

编辑:

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

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

将interval函数改为递归的
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);
异步函数doscorl(){ scrollBy(0,scrollHeight); const scrollTop=document.documentElement.scrollTop; 让lastDate=null; 如果(maxDate){ const html=new XMLSerializer().serializeToString(document.doctype)+document.documentElement.outerHTML; 等待提取日期(html)。然后((日期)=>{ lastDate=日期; }); } 如果(scrollTop==lastScrollTop|| (maxDate&&lastDate&&maxDate.getTime()>=lastDate.getTime()){ //不需要“清除间隔”: 解决(); }否则{ lastScrollTop=scrollTop; //递归设置超时:
setTimeout(Doscorl,2000);//将间隔改为函数,并使用setTimeout对未来的函数调用进行排队

const interval = async function () { // instead of setInterval
然后使用setTimeout函数将未来的呼叫排队:

setTimeout(interval, 2000);

小提琴示例:

使用以下代码:

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

如果有人想要一个更新的解决方案,有一个react timeout,它会在卸载包装好的组件时自动取消任何延迟的计时器

更多信息

https://www.npmjs.com/package/react-timeout

npm i react-timeout
在使用wait时,您可以执行以下操作

  handleClick = async() => {
    try {
      await this.props.getListAction().then(()=>{
        this.timeOut = this.props.setTimeOut(this.handleClick, 10000);
      });

    } catch(err) {
      clearTimeout(this.timeOut);
    }
  }

我通常选择这种解决方案。我认为它更干净:

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

您的
循环
函数将返回一个承诺。您可以等待它停止循环,也可以放弃它。

当使用异步函数作为
setInterval
setTimeout
的参数时,请确保在try/catch中包装任何可能引发错误的操作,以避免未处理的错误,并且在Node.js上,不要执行以下操作:ll
进程。退出
,因为它将先占事件循环,而不考虑计时器。更多详细信息,请参见。

您将所有这些都放在
try
块中-其他所有内容都是相同的请用您的解决方案检查我编辑的代码。我尝试过,但使用这种方法,它只会滚动一次。无论我是否注释掉e包含等待调用的if语句。以前它一直滚动,直到满足if条件。这个resolve()调用是什么?它没有在块中定义。另外,它不应该是scroll()吗而不是滚动?@NirO。这就是
try
块中的代码应该是什么。
resolve
wait new Promise(异步(解析,拒绝)=>{
拒绝中的错误是什么?@aanken它只滚动一次,然后在一段时间后抛出
error:protocol error(Runtime.callfunction):Promise已收集
。堆栈跟踪指向一些木偶程序函数。请尝试将interval函数移动到父Promise函数的顶部,并将Try-catch块移动到interval内。在Promise行,尝试返回Promise并从Promise函数中删除async关键字。您是否可以将其作为答案写入此处。Thank你!我一直在寻找这个解决方案(很长时间)当心setInterval会收到一个它不理解的承诺,没有人问过Reacts这是绝对平滑的。我正在将我的调用从mssqlserver转换到node,这解决了其他人发布的函数无法解释的逻辑步骤:在启动任何延迟之前完全完成语句。这很漂亮