-
Notifications
You must be signed in to change notification settings - Fork 9.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Control networkidle wait time #1353
Comments
I had same question. My web application will send servel requests but I can't even set response time. |
+1 I don't think the new values |
This is very important. I just updated Any reason this is now hardcoded? |
@tommedema The implementation of The good news is that it's easy to implement a self-baked network-idle watcher, for example: function waitForNetworkIdle(page, timeout, maxInflightRequests = 0) {
page.on('request', onRequestStarted);
page.on('requestfinished', onRequestFinished);
page.on('requestfailed', onRequestFinished);
let inflight = 0;
let fulfill;
let promise = new Promise(x => fulfill = x);
let timeoutId = setTimeout(onTimeoutDone, timeout);
return promise;
function onTimeoutDone() {
page.removeListener('request', onRequestStarted);
page.removeListener('requestfinished', onRequestFinished);
page.removeListener('requestfailed', onRequestFinished);
fulfill();
}
function onRequestStarted() {
++inflight;
if (inflight > maxInflightRequests)
clearTimeout(timeoutId);
}
function onRequestFinished() {
if (inflight === 0)
return;
--inflight;
if (inflight === maxInflightRequests)
timeoutId = setTimeout(onTimeoutDone, timeout);
}
}
// Example
await Promise.all([
page.goto('https://google.com'),
waitForNetworkIdle(page, 500, 0), // equivalent to 'networkidle0'
]); |
thanks @aslushnikov , I guess I will publish that as a npm package once I found some time |
I'm doing this now which I think should work as well (in a lot of cases)? await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle0' }),
page.evaluate(() => history.pushState(null, null, '#')),
]); |
I couldn't get @aslushnikov 's example to catch all the request finishes / failures so I modified it.
|
The |
@aslushnikov I am trying to fetch multiple dynamic pages using puppeteer. The default
I found that there is no response or timeout error being thrown as the promise for |
This waits until the timeout anyway! |
I couldn't get @aslushnikov's example to work.
Here is my working implementation: function waitForNetworkIdle({ page, timeout = 30000, waitForFirstRequest = 1000, maxInflightRequests = 0 }) {
let inflight = 0;
let resolve;
let reject;
let firstRequestTimeoutId;
let timeoutId;
function cleanup() {
clearTimeout(timeoutId);
clearTimeout(firstRequestTimeoutId);
/* eslint-disable no-use-before-define */
page.removeListener('request', onRequestStarted);
page.removeListener('requestfinished', onRequestFinished);
page.removeListener('requestfailed', onRequestFinished);
/* eslint-enable no-use-before-define */
}
function check() {
if (inflight === 0 || inflight <= maxInflightRequests) {
cleanup();
resolve();
}
}
function onRequestStarted() {
clearTimeout(firstRequestTimeoutId);
inflight += 1;
}
function onRequestFinished() {
inflight -= 1;
check();
}
function onTimeout() {
cleanup();
reject(new Error('Timeout'));
}
function onFirstRequestTimeout() {
cleanup();
resolve();
}
page.on('request', onRequestStarted);
page.on('requestfinished', onRequestFinished);
page.on('requestfailed', onRequestFinished);
timeoutId = setTimeout(onTimeout, timeout);
firstRequestTimeoutId = setTimeout(onFirstRequestTimeout, waitForFirstRequest);
return new Promise((res, rej) => { resolve = res; reject = rej; });
}
|
@mifi You left out any implementation similar to how networkIdle0 works where it delays 500ms before returning to catch delayed/rate limited network requests. There are good reasons to delay before assuming as soon as you hit zero requests there will be no further requests. We aimed to reduce this 500ms minimum down to 50-200ms to reduce PDF generation times. Here's an update of your version with a waitForLastRequest time added. function waitForNetworkIdle({ page, timeout = 30000, waitForFirstRequest = 1000, waitForLastRequest = 200, maxInflightRequests = 0 }) {
let inflight = 0;
let resolve;
let reject;
let firstRequestTimeoutId;
let lastRequestTimeoutId;
let timeoutId;
maxInflightRequests = Math.max(maxInflightRequests, 0);
function cleanup() {
clearTimeout(timeoutId);
clearTimeout(firstRequestTimeoutId);
clearTimeout(lastRequestTimeoutId);
/* eslint-disable no-use-before-define */
page.removeListener('request', onRequestStarted);
page.removeListener('requestfinished', onRequestFinished);
page.removeListener('requestfailed', onRequestFinished);
/* eslint-enable no-use-before-define */
}
function check() {
if (inflight <= maxInflightRequests) {
clearTimeout(lastRequestTimeoutId);
lastRequestTimeoutId = setTimeout(onLastRequestTimeout, waitForLastRequest);
}
}
function onRequestStarted() {
clearTimeout(firstRequestTimeoutId);
clearTimeout(lastRequestTimeoutId);
inflight += 1;
}
function onRequestFinished() {
inflight -= 1;
check();
}
function onTimeout() {
cleanup();
reject(new Error('Timeout'));
}
function onFirstRequestTimeout() {
cleanup();
resolve();
}
function onLastRequestTimeout() {
cleanup();
resolve();
}
page.on('request', onRequestStarted);
page.on('requestfinished', onRequestFinished);
page.on('requestfailed', onRequestFinished);
timeoutId = setTimeout(onTimeout, timeout); // Overall page timeout
firstRequestTimeoutId = setTimeout(onFirstRequestTimeout, waitForFirstRequest);
return new Promise((res, rej) => { resolve = res; reject = rej; });
} |
For people who can be interested, I testing a It's simple and works like a charm:
👌 |
☝️ this great snippet by @simonhaenisch worked for most cases for me, but replacing the path with await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle0' }),
page.evaluate(() => history.pushState(null, null, null)),
]); |
@lehni thanks for the trick! Can you tell us a public URL to see the difference? |
@Kikobeats sadly I can't. I tried the solution by @simonhaenisch in our e2e tests and noticed some strange fails in some situations that I thought could be linked to the use of the hash (just a hunch). I replaced it with |
* fix: close dialog before take the screenshot * build: wait for resolve url edge cases related: https://github.com/puppeteer/puppeteer/issues/1353\#issuecomment-723164059
For our application, there is a significant gap (~1-2s) between when the main app requests are finished and the data resource requests are started. Currently the
networkidle
option waits for the network to be idle for 500ms. It would be nice to configure this value so that we can wait for all the requests to finish.The text was updated successfully, but these errors were encountered: