Кукольник - дождаться завершения сетевых запросов после page.select () - PullRequest
0 голосов
/ 16 января 2020

Есть ли способ дождаться разрешения сетевых запросов после выполнения действия на странице перед выполнением нового действия в Puppeteer?

Мне нужно взаимодействовать с меню выбора на странице, используя page.select() который заставляет динамические c изображения и шрифты загружаться на страницу. Мне нужно дождаться завершения этих запросов перед выполнением следующего действия.

-

Предостережения:

  1. Я не могу перезагрузить страницу или go на новый URL.
  2. Я не знаю, какие могут быть типы запросов или сколько

-

// launch puppeteer
const browser = await puppeteer.launch({});

// load new page
const page = await browser.newPage();

// go to URL and wait for initial requests to resolve
await page.goto(pageUrl, {
  waitUntil: "networkidle0"
});

// START LOOP
for (let value of lotsOfValues) {

  // interact with select menu
  await page.select('select', value);

  // wait for network requests to complete (images, fonts)
  ??

  // screenshot page with new content
  await pageElement.screenshot({
    type: "jpeg",
    quality: 100
  });

} // END LOOP

// close
await browser.close();

1 Ответ

0 голосов
/ 17 января 2020

Ответ на этот вопрос заключается в использовании page.setRequestInterception(true); и отслеживании последующих запросов, ожидая их повторного разрешения, прежде чем перейти к следующему заданию ( спасибо @ Guarev за точку в правильном направлении).

Этот модуль (https://github.com/jtassin/pending-xhr-puppeteer) делает именно это, но для запросов XHR. Я изменил его, чтобы искать типы 'image' и 'font'.

Окончательный код выглядит примерно так:

// launch puppeteer
const browser = await puppeteer.launch({});

// load new page
const page = await browser.newPage();

// go to URL and wait for initial requests to resolve
await page.goto(pageUrl, {
  waitUntil: "networkidle0"
});

// enable this here because we don't want to watch the initial page asset requests (which page.goto above triggers) 
await page.setRequestInterception(true);

// custom version of pending-xhr-puppeteer module
let monitorRequests = new PuppeteerNetworkMonitor(page);

// START LOOP
for (let value of lotsOfValues) {

  // interact with select menu
  await page.select('select', value);

  // wait for network requests to complete (images, fonts)
  await monitorRequests.waitForAllRequests();

  // screenshot page with new content
  await pageElement.screenshot({
    type: "jpeg",
    quality: 100
  });

} // END LOOP

// close
await browser.close();

NPM Модуль

class PuppeteerNetworkMonitor {

    constructor(page) {
        this.promisees = [];
        this.page = page;
        this.resourceType = ['image'];
        this.pendingRequests = new Set();
        this.finishedRequestsWithSuccess = new Set();
        this.finishedRequestsWithErrors = new Set();
        page.on('request', (request) => {
            request.continue();
            if (this.resourceType.includes(request.resourceType())) {
                this.pendingRequests.add(request);
                this.promisees.push(
                    new Promise(resolve => {
                        request.resolver = resolve;
                    }),
                );
            }
        });
        page.on('requestfailed', (request) => {
            if (this.resourceType.includes(request.resourceType())) {
                this.pendingRequests.delete(request);
                this.finishedRequestsWithErrors.add(request);
                if (request.resolver) {
                    request.resolver();
                    delete request.resolver;
                }
            }
        });
        page.on('requestfinished', (request) => {
            if (this.resourceType.includes(request.resourceType())) {
                this.pendingRequests.delete(request);
                this.finishedRequestsWithSuccess.add(request);
                if (request.resolver) {
                    request.resolver();
                    delete request.resolver;
                }
            }
        });
    }

    async waitForAllRequests() {
        if (this.pendingRequestCount() === 0) {
            return;
        }
        await Promise.all(this.promisees);
    }

    pendingRequestCount() {
        return this.pendingRequests.size;
    }
}

module.exports = PuppeteerNetworkMonitor;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...