乐闻世界logo
搜索文章和话题

Puppeteer 中有哪些等待机制?如何正确使用它们来处理异步操作?

2月19日 19:40

Puppeteer 提供了多种等待机制来处理异步操作和页面加载,确保在执行操作前页面状态已就绪。

1. page.waitForNavigation()

等待页面导航完成,适用于点击链接、提交表单等会触发页面跳转的操作。

javascript
await Promise.all([ page.waitForNavigation(), page.click('#submit-button') ]);

参数选项:

  • waitUntil: 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'
  • timeout: 超时时间(毫秒)

2. page.waitForSelector(selector)

等待指定选择器出现在页面中。

javascript
await page.waitForSelector('.result-item', { visible: true });

参数选项:

  • visible: 等待元素可见
  • hidden: 等待元素隐藏
  • timeout: 超时时间

3. page.waitForXPath(xpath)

等待 XPath 选择器匹配的元素。

javascript
await page.waitForXPath('//div[@class="content"]');

4. page.waitForFunction(pageFunction, ...args)

等待自定义函数返回真值,最灵活的等待方式。

javascript
await page.waitForFunction( () => document.querySelectorAll('.item').length > 5 ); // 带参数 await page.waitForFunction( (count) => document.querySelectorAll('.item').length >= count, {}, 10 );

5. page.waitForTimeout(milliseconds)

等待指定时间(已废弃,建议使用 setTimeout)。

javascript
// 旧方法(已废弃) await page.waitForTimeout(1000); // 新方法 await new Promise(resolve => setTimeout(resolve, 1000));

6. page.waitForResponse(urlOrPredicate)

等待特定的网络响应。

javascript
// 等待特定 URL 的响应 await page.waitForResponse('https://api.example.com/data'); // 使用谓词函数 await page.waitForResponse(response => response.url().includes('/api/') && response.status() === 200 );

7. page.waitForRequest(urlOrPredicate)

等待特定的网络请求。

javascript
await page.waitForRequest(request => request.url().includes('/api/data') );

8. page.waitForFrame(frame)

等待指定的 iframe 加载完成。

javascript
const frame = await page.waitForFrame('iframe-name');

最佳实践:

1. 选择合适的等待方法:

  • 导航操作 → waitForNavigation
  • 元素操作 → waitForSelector
  • 复杂条件 → waitForFunction
  • API 调用 → waitForResponse

2. 设置合理的超时时间:

javascript
await page.waitForSelector('.element', { timeout: 5000 // 5 秒超时 });

3. 使用 Promise.all 并行等待:

javascript
await Promise.all([ page.waitForNavigation(), page.click('#link'), page.waitForSelector('.loaded') ]);

4. 处理超时异常:

javascript
try { await page.waitForSelector('.element', { timeout: 3000 }); } catch (error) { console.log('Element not found within timeout'); }

5. 优化等待策略:

javascript
// 等待网络空闲(推荐) await page.waitForNavigation({ waitUntil: 'networkidle2' }); // 等待特定元素可见 await page.waitForSelector('.element', { visible: true });

常见问题解决:

问题 1:元素存在但不可见

javascript
// 解决方案:等待元素可见 await page.waitForSelector('.element', { visible: true });

问题 2:动态加载内容

javascript
// 解决方案:使用 waitForFunction 检查内容 await page.waitForFunction(() => document.querySelectorAll('.item').length > 0 );

问题 3:SPA 路由变化

javascript
// 解决方案:等待 URL 变化 await page.waitForFunction(() => window.location.pathname === '/new-page' );
标签:Puppeteer