首页 > 解决方案 > 检查所有要加载的帧

问题描述

我想检查页面上的所有框架是否都已加载。我不太明白这一点,其中一部分是我不完全理解框架事件(特别是什么时候发生frameattachedframenavigated事件触发?)。

这是我现在正在做的事情,但我多次绑定到同一个页面事件而不是框架事件。

function waitForFrames() {
  return Promise.all(page.frames().map((frame) => {
    return new Promise(resolve => {
      page.on('framenavigated', resolve);
    });
  })).then(() => {
    console.log('Frames loaded');
  })
    .catch(e => {
      console.log(e.message);
    });
}

如何检查是否已加载所有帧?

标签: puppeteer

解决方案


Frame 类的Puppeteer 文档有助于解释帧事件:

类别:框架

在每个时间点,页面都会通过page.mainFrame()frame.childFrames()方法公开其当前的框架树。

Frame对象的生命周期由三个事件控制,在页面对象上分派:

  • 'frameattached'- 当框架附加到页面时触发。框架只能附加到页面一次。
  • 'framenavigated'- 当框架提交导航到不同的 URL 时触发。
  • 'framedetached'- 当框架与页面分离时触发。框架只能从页面分离一次。

您可以使用以下函数等待一帧(按名称):

const wait_for_frame = (page, frame_name) => {
  let fulfill_promise;
  const promise = new Promise(x => fulfill_promise = x);
  
  check_frame();
  
  return promise;
  
  const check_frame = () => {
    const frame = page.frames().find(current_frame => current_frame.name() === frame_name);
    
    if (frame) {
      fulfill_promise(frame);
    } else {
      page.once('frameattached', check_frame);
    }
  };
};

// Waiting for frame to become attached:
const frame = await wait_for_frame(page, frame_name);

// Waiting for frame to contain a certain selector:
await frame.waitForSelector(selector);

const button = await frame.$(selector);

button.click();

上面的代码片段受以下来源的影响和改进:Source


最后,您可以await逐个循环播放帧。


推荐阅读