布袋戏:如何收听对象事件

Vic*_*Vic 8 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);
Run Code Online (Sandbox Code Playgroud)

我希望能够监听window对象(或其他任何JS对象)调度的事件。如何在Puppeteer中执行此操作?

Tho*_*orf 18

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

// 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(/* ... */);
Run Code Online (Sandbox Code Playgroud)

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

正如评论中发布的那样,可以在puppeteer examples 中找到更复杂的示例


Joh*_*rty 8

更简单的方法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)
    ]);
}
Run Code Online (Sandbox Code Playgroud)

来源


mfl*_*din 5

如果你想真正等待自定义事件,你可以这样做。

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 || '');
Run Code Online (Sandbox Code Playgroud)

基于https://github.com/puppeteer/puppeteer/blob/main/examples/custom-event.js上的示例构建