检查所有要加载的帧

时间:2018-06-26 20:56:36

标签: puppeteer

我想检查页面上的所有框架是否均已加载。我不太清楚这一点,部分原因是我不完全了解帧事件(特别是何时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);
    });
}

如何检查所有框架均已加载?

2 个答案:

答案 0 :(得分:1)

Frame类的Puppeteer Documentation帮助解释框架事件:

  

类别:框架

     

页面在每个时间点都通过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帧。

答案 1 :(得分:0)

使用 Grant 的解决方案时,我遇到了问题,即我正在寻找的 iFrame 有时会在页面加载后分离,然后(重新)附加和导航。在这种情况下,waitForSelector 会产生一个异常“iFrame got detached”。在我看来,出现在 page.frames() 中的框架并不能保证实际被附加。

所以我改变了他的解决方案的wait_for_frame函数来覆盖这种情况。这也包括页面上有多个 iFrame 的情况。

const wait_for_frame = (page, frame_name) => {

    const check_frame = frame => {
        if (frame.name() == frame_name) {
            fulfill_promise(frame);
            page.off('framenavigated', check_frame);
        }
    };
    
    let fulfill_promise;
    const promise = new Promise(x => fulfill_promise = x);
    page.on('framenavigated', check_frame);
  
    return promise;
};

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