Как я могу установить опцию тайм-аута на каждый запрос в функции page.goto - PullRequest
0 голосов
/ 30 июня 2018

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

Следуйте мой код test.js:

const browser = await puppeteer.launch();
const page = await browser.newPage();
page.on('request', request => {
    console.log(request.url())
})
await page.goto(process.argv[2], {timeout: 10000}).then( () => {
}, () => {
    console.log("timeout");
}); 
browser.close();
node test.js http://ipv6ready.wanwuyunlian.com:8080/

http://ipv6ready.wanwuyunlian.com:8080/  
http://ipv6ready.wanwuyunlian.com:8080/js/bootstrap.min.js
http://ipv6ready.wanwuyunlian.com:8080/js/echarts/echarts.min.js
https://www.google-analytics.com/analytics.js    
http://ipv6ready.wanwuyunlian.com:8080/js/echarts/macarons.js
https://www.google-analytics.com/analytics.js 

Запрос analytics.js очень медленный из-за тайм-аута соединения; это заблокирует page.goto на долгое время, оставшиеся ресурсы не будут запрошены, я хочу прервать этот запрос и продолжить запрашивать оставшиеся ресурсы.

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

Если вы хотите просто отменить запросы на основе их URL, в кукловоде есть режим для этого: page.setRequestInterception . Образец документации, адаптированный к вашему варианту использования:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();

  // turn on requests intercepting and cancellation capability
  await page.setRequestInterception(true);

  page.on('request', interceptedRequest => {

    console.log(interceptedRequest.url());

    if (interceptedRequest.url().includes("google-analytics.com"))
    {
      console.log("cancelled!");
      interceptedRequest.abort();
    }
    else
    {
      interceptedRequest.continue();
    }
  });
  await page.goto('http://ipv6ready.wanwuyunlian.com:8080/');
  await browser.close();
});
0 голосов
/ 02 июля 2018

Есть два способа решения этой проблемы. Во-первых, вместо * по умолчанию networkidle0 следует использовать networkidle2 («считать навигацию завершенной, если в течение не менее 500 мсек не более 2 сетевых подключений»), чтобы до двух запросов могли выполняться медленно, не влияя на вашу работу. код:

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(process.argv[2], {waitUntil: "networkidle2"}).then( () => {
}, (e) => {
    console.error("Error", e);
}); 
browser.close();

В качестве альтернативы, для реализации тайм-аутов на отдельных запросах страниц я бы предложил использовать модуль тайм-аутов, например p-timeout:

const pTimeout = require("p-timeout");

const shorterTimeout = 10000;
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', async (request) => {
    if (!shouldImplementTimeout(request.url())) {
        await request.continue();
    }

    await pTimeout(request.continue(), shorterTimeout)
        .catch((e) => {
            console.error(request.url(), "failed:", e);
            await request.abort("timedout");
        });
})
await page.goto(process.argv[2]).then( () => {
}, (e) => {
    console.error("Error", e);
}); 
browser.close();

Вам нужно будет написать shouldImplementTimeout, что должно вернуть true, если запрос требует более короткого времени ожидания.

...