傀儡师:等待 N 秒,然后继续下一行

puppeteer: wait N seconds before continuing to the next line

提问人:Pipo 提问时间:10/25/2017 最后编辑:BenjaminPipo 更新时间:8/25/2023 访问量:228686

问:

puppeteer 中,我想等待一个定义的时间,然后再转到下一行代码。

我试图将一个放在评估函数中,但它似乎被简单地忽略了setTimeout

console.log('before waiting');
await page.evaluate(async() => {
  setTimeout(function(){
      console.log('waiting');
  }, 4000)
});
console.log('after waiting');

这段代码不要等待,只需在等待之前等待之后编写

你知道怎么做吗?

JavaScript 节点 .js Chromium Puppeteer 浏览器测试

评论

0赞 Osama 10/25/2017
await page.evaluate(async() => { setTimeout(function(){ console.log('waiting');你的代码不对,上面是对的

答:

-4赞 atopcu 10/25/2017 #1

您的语法不完整。
试试这个...

await page.evaluate(async() => {
    setTimeout(function(){
        console.log('waiting');
    }, 4000)
});

评论

0赞 Pipo 10/25/2017
感谢您的帮助,我编辑了问题,很抱歉犯了错误,但我真的问如何等待
232赞 Md. Abu Taher 10/27/2017 #2

可以使用一点承诺功能,

function delay(time) {
   return new Promise(function(resolve) { 
       setTimeout(resolve, time)
   });
}

然后,只要你想要延迟,就调用它。

console.log('before waiting');
await delay(4000);
console.log('after waiting');

如果必须使用 puppeteer,请使用内置的 waitForTimeout 函数。

await page.waitForTimeout(4000)

如果仍想使用 page.evaluate,请在 4 秒后解决它。你没有解决任何事情。

await page.evaluate(async() => {
    await new Promise(function(resolve) { 
           setTimeout(resolve, 1000)
    });
});

但我想你可以简单地使用前两个例子。

评论

0赞 Thiago C. S Ventura 12/30/2017
你确定这是有效的吗?你不能在 page.evaluate() 中使用 delay(),它不属于它的上下文。
3赞 Md. Abu Taher 12/30/2017
我很确定延迟函数和 page.evaluate 是不同的例子。
3赞 Maxime Lechevallier 12/17/2020
waitFor已弃用,请改用。waitForTimeout
0赞 Alston 7/10/2022
是斯马克。但是我无法弄清楚为什么“function delay(time) { return new Promise(function(resolve) { setTimeout(resolve, time) }); }”有效...
1赞 ggorlen 9/11/2022
waitForTimeout也被弃用了。最好找到一个更好的谓词来阻止:、、、等。waitForFunctionwaitForNetworkIdlewaitForResponsewaitForSelector
61赞 Grant Miller 10/29/2018 #3

您可以使用以下选项之一等待一秒钟

await page.waitFor(1000);
await frame.waitFor(1000);
await new Promise(r => setTimeout(r, 1000));

或者,有许多 Puppeteer 函数包含内置选项,在某些事件之间等待可能会派上用场:delay

// Click Delay
// Time to wait between mousedown and mouseup in milliseconds. Defaults to 0.

await page.click('#example', {delay: 1000});
await frame.click('#example', {delay: 1000});
await elementHandle.click({delay: 1000});
await page.mouse.click(0, 0, {delay: 1000});

// Type Delay
// Time to wait between key presses in milliseconds. Defaults to 0.

await page.type('#example', 'Hello, world!', {delay: 1000});
await frame.type('#example', 'Hello, world!', {delay: 1000});
await elementHandle.type('Hello, world!', {delay: 1000});
await page.keyboard.type('Hello, world!', {delay: 1000});

// Press Delay
// Time to wait between keydown and keyup in milliseconds. Defaults to 0.

await elementHandle.press('Backspace', {delay: 1000});
await page.keyboard.press('Backspace', {delay: 1000});

评论

3赞 Scott Jodoin 12/31/2021
waitFor 已弃用,将被删除。新函数是 waitForTimeout github.com/puppeteer/puppeteer/issues/6214
1赞 Ciprian Tomoiagă 4/4/2023
waitForTimeout 也已弃用
-1赞 Xin 2/24/2019 #4
await new Promise(_func=> setTimeout(_func, 5000));

评论

0赞 ggorlen 12/9/2022
许多其他答案已经对此提供了明确的解释。重命名为很奇怪。不仅如此,如果我们能帮上忙,我们真的不应该在 Puppeteer 中使用它。resolve_func
4赞 Yordan 2/25/2019 #5

试试这个功能。

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

使用它

  async function demo() {
    console.log('Waiting...');
    await sleep(3000);
    console.log('ok');
  }

  demo();
120赞 Huckleberry Carignan 2/26/2019 #6

我一直在使用:

await page.waitForTimeout(3000);

其中 3000 是毫秒 这似乎对我有用。

评论

9赞 A McGuinness 11/8/2020
waitfor() 已被剥夺。请改用 page.waitForTimeout(1000)
4赞 LeMoussel 1/30/2023
page.waitForTimeout()现在已经过时了。替换为new Promise(r => setTimeout(r, milliseconds));
27赞 MatthewThomas.dev 10/1/2020 #7

page.waitFor 现已弃用。

现在建议 page.waitForTimeout 暂停脚本执行给定的毫秒数,然后再继续:

await page.waitForTimeout(1000)

评论

1赞 Muhammad Uzair 7/27/2022
请更新文档链接
10赞 ggorlen 9/11/2022 #8

其他答案已经显示了如何睡觉,但现在终于被弃用了,我想我会添加我想添加一段时间的答案:page.waitForTimeout

不要睡觉!它会导致一个竞争条件,破坏 Puppeteer 的事件驱动性质,引入不必要的脆弱性。几乎总是有一个更好的谓词可以等待,无论是显式还是使用 Locator API:

  • 您是否正在等待 CSS 选择器、aria 标签、文本或 XPath 出现?尝试(可选使用适当的内置选择器)。waitForSelector
  • 你在等待导航吗?尝试或调整 上的选项。waitForNavigationwaitUntilgoto
  • 您是否正在等待网络事件或状态?尝试 或 。waitForRequestwaitForResponsewaitForNetworkIdle
  • 你在等待弹出窗口吗?尝试page.on(“dialog”, ....
  • 您是否正在等待一些任意谓词,例如出现最小数量的子元素?尝试。waitForFunction
  • 您是否试图避免被发现?尝试。slowMo
  • 别的?运行一个块并添加您自己的代码以等待 DOM 突变或轮询,并根据您的需求有效地重新实现。evaluatesetIntervalrequestAnimationFramewaitForFunction

waitForFunction特别是未充分利用,但它增加了大量的可靠性和精度,而这并没有。waitForTimeout

如果所有其他方法都失败了,你必须阻止脚本,你可以延迟,但我已经编写了数百个 Puppeteer 脚本,并且从未使用过任何睡眠变体,所以我非常确信这基本上是不必要的。

请参阅我关于 Puppeteer Antipatterns 的博客文章,以进一步分析为什么您应该避免以任何形式睡觉,除非是绝对的最后手段。

另请参阅 waitForTimeout 的 Playwright 文档,该文档与 Puppeteer 方法基本相同:

气馁

永远不要在生产中等待超时。等待时间的测试本质上是不稳定的。使用自动等待的定位器操作和 Web 断言。

上面需要注意的是:在开发脚本时,睡眠对于临时调试很有用。

评论

1赞 Moinul Moin 3/11/2023
100% 同意这句话:“waitForFunction 尤其没有得到充分利用,但它增加了 waitForTimeout 没有的大量可靠性和精确度。