Puppeteer:如何收听对象事件

时间:2017-11-04 04:44:06

标签: javascript google-chrome headless puppeteer

是否可以侦听页内对象调度的事件?假设我在我去的页面中有这个代码:

var event = new CustomEvent('status', { detail: 'ok' });
window.addEventListener('status', function(e) {
  console.log('status: ', e.detail);
});
setInterval(window.dispatchEvent, 1000, event);

我希望能够监听由窗口对象(或任何其他JS对象)调度的事件。我怎么能在Puppeteer中做到这一点?

3 个答案:

答案 0 :(得分:3)

首先,您必须公开一个可以在页面内调用的函数。其次,您监听事件并调用公开的函数并传递事件数据。

// Expose a handler to the page
await page.exposeFunction('onCustomEvent', ({ type, detail }) => {
    console.log(`Event fired: ${type}, detail: ${detail}`);
});

// listen for events of type 'status' and
// pass 'type' and 'detail' attributes to our exposed function
await page.evaluateOnNewDocument(() => {
    window.addEventListener('status', ({ type, detail }) => {
        window.onCustomEvent({ type, detail });
    });
});

await page.goto(/* ... */);

如果页面中现在触发了一个事件status(如您提供的代码),您会看到它已记录在Node.js应用程序的控制台中。

如评论中所述,可以在puppeteer examples中找到更复杂的示例。

答案 1 :(得分:2)

更简单的方法await waitForEvent('event-name', 10)

/**
 * Wait for the browser to fire an event (including custom events)
 * @param {string} eventName - Event name
 * @param {integer} seconds - number of seconds to wait.
 * @returns {Promise} resolves when event fires or timeout is reached
 */
async function waitForEvent(eventName, seconds) {

    seconds = seconds || 30;

    // use race to implement a timeout
    return Promise.race([

        // add event listener and wait for event to fire before returning
        page.evaluate(function(eventName) {
            return new Promise(function(resolve, reject) {
                document.addEventListener(eventName, function(e) {
                    resolve(); // resolves when the event fires
                });
            });
        }, eventName),

        // if the event does not fire within n seconds, exit
        page.waitForTimeout(seconds * 1000)
    ]);
}

Source

答案 2 :(得分:0)

如果您想实际等待自定义事件,则可以通过这种方式进行。

const page = await browser.newPage();

/**
  * Attach an event listener to page to capture a custom event on page load/navigation.
  * @param {string} type Event name.
  * @return {!Promise}
  */
function addListener(type) {
  return page.evaluateOnNewDocument(type => {
    // here we are in the browser context
    document.addEventListener(type, e => {
      window.onCustomEvent({ type, detail: e.detail });
    });
  }, type);
}

const evt = await new Promise(async resolve => {
  // Define a window.onCustomEvent function on the page.
  await page.exposeFunction('onCustomEvent', e => {
    // here we are in the node context
    resolve(e); // resolve the outer Promise here so we can await it outside
  });
  await addListener('status'); // setup listener for "status" custom event on page load
  await page.goto('http://example.com');  // N.B! Do not use { waitUntil: 'networkidle0' } as that may cause a race condition
});

console.log(`${evt.type} fired`, evt.detail || '');

基于https://github.com/GoogleChrome/puppeteer/blob/master/examples/custom-event.js

上的示例