How should I wait for the re-render to occur after I apply a style to a div? Is there any event for this?
Or else I am getting an error of Error: Could not compute box model. when calling DOM.getBoxModel() right after applying a style.
const CDP = require('chrome-remote-interface');
const chromeLauncher = require('chrome-launcher');
chromeLauncher.launch({
port: 9222,
chromeFlags: [
'--disable-gpu',
'--headless',
],
}).then(async (chrome) => {
const client = await CDP({ port: chrome.port });
client.on('error', (err) => {
console.error(err);
});
const { Page, DOM, CSS } = client;
await Page.enable();
await Page.navigate({
url: 'http://github.com',
});
await Page.loadEventFired();
await DOM.enable();
await CSS.enable();
const { root: { nodeId: docNodeId } } = await DOM.getDocument();
const { nodeId: formId } = await DOM.querySelector({
nodeId: docNodeId,
selector: 'form[action="/join"]',
});
await CSS.setEffectivePropertyValueForNode({
nodeId: formId,
propertyName: 'display',
value: 'none',
});
await CSS.setEffectivePropertyValueForNode({
nodeId: formId,
propertyName: 'display',
value: 'block',
});
// Here the above code applies the style
// but doesn't wait for the render to finish.
await DOM.getBoxModel({ nodeId: formId });
// So after this line it is throwing an error saying
// Could not compute box model
client.close();
chrome.kill();
}).catch((err) => {
console.error(err);
});
| Component | Version
|-|-
| Operating system | OSX 10.12.6
| Node.js | v8.2.1
| Chrome Canary | v62.0.3187.0
| chrome-remote-interface | v0.24.3
Is Chrome running in a container? NO
I'd wait for two sequential requestAnimationFrame()s to fire. then you can be sure these changes have applied.
Okay, so I wrote a function like this.
async function waitForNextAnimationFrame(count = 1) {
const { Runtime } = client;
for (let i = 0; i < count; i++) {
await Runtime.evaluate({
expression: 'new Promise((resolve) => window.requestAnimationFrame(resolve));',
awaitPromise: true,
});
}
}
And used it like this.
await CSS.setEffectivePropertyValueForNode({
nodeId: formId,
propertyName: 'display',
value: 'block',
});
await waitForNextAnimationFrame(2);
await DOM.getBoxModel({ nodeId: formId });
Is this the right approach of doing this?
@Jimut it's IMO the right approach; with this change the Could not compute box model. error doesn't seem to happen.
Yet, if I run the snippet continuously DOM.querySelector seldom returns a 0 nodeId, not sure why.
Yet, if I run the snippet continuously DOM.querySelector seldom returns a 0 nodeId, not sure why.
Well, lol, I apparently triggered the abuse mechanism of GitHub... ignore this.
Is this the right approach of doing this?
It's not a huge deal IMO but i would just hardcode the 2 nested raf inside a single runtime.evaluate...
roughly like
await Runtime.evaluate({
expression: `new Promise((resolve) =>
window.requestAnimationFrame(_ =>
window.requestAnimationFrame(resolve)));`,
awaitPromise: true
});
Thank you a lot @paulirish @cyrus-and.
@Jimut you're welcome, please close this if you've found an acceptable solution.
Most helpful comment
I'd wait for two sequential requestAnimationFrame()s to fire. then you can be sure these changes have applied.