Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteThe correct callback depends on what you mean by “image.” For an interactive Plotly chart, wait for the promise returned by Plotly.newPlot(). To run code after every plotting pass, listen for plotly_afterplot. For a static export, await Plotly.toImage(); that promise tells you the image data URL has been generated, not necessarily that a browser has finished decoding an <img> element.
Choose the completion signal that matches your goal
Plotly has three separate milestones: drawing a chart into a graph div, plotting again after an update, and generating a static image export. Treating them as the same event can make code run too early or run repeatedly when you expected one call.
| What must be complete? | Use | Meaning |
|---|---|---|
| Initial interactive chart render | Plotly.newPlot(...).then(...) |
The initial newPlot operation has completed. |
| Every plotting pass, including updates | graphDiv.on('plotly_afterplot', handler) |
Plotly has plotted the graph again. It may fire multiple times. |
| Plotly-generated static image | Plotly.toImage(...).then(...) or await Plotly.toImage(...) |
The exported image data URL is available. |
These signals are documented in Plotly’s JavaScript event guide, function reference and static image export guide.
Run code once after the initial chart render
Plotly.newPlot draws a new plot into a div and returns a promise. Attach then when you need one post-render action, such as enabling a button, measuring the graph container or starting application logic that requires the initial graph.
#1 Best Overall
const data = [
{
x: ['Mon', 'Tue', 'Wed'],
y: [12, 19, 14],
type: 'bar'
}
];
const layout = {
title: 'Weekly values',
width: 800,
height: 500
};
Plotly.newPlot('myDiv', data, layout)
.then((gd) => {
// The initial chart render has completed.
runMyCode(gd);
});
function runMyCode(graphDiv) {
console.log('Plot is ready:', graphDiv);
document.querySelector('#exportButton').disabled = false;
}
The promise resolves with the graph div, conventionally named gd. Passing the element rather than its ID is also valid:
const gd = document.getElementById('myDiv');
Plotly.newPlot(gd, data, layout).then((graphDiv) => {
runMyCode(graphDiv);
});
This callback describes completion of Plotly’s initial plotting operation. It is not a general browser notification that every descendant image, font or external resource has finished decoding.
Run code after every Plotly plotting pass
Use plotly_afterplot when the action must happen after the initial plot and after later plotting operations. Plotly documents this event as running each time a chart is plotted, including plotting caused by restyling or relayout.
const gd = document.getElementById('myDiv');
gd.on('plotly_afterplot', () => {
runAfterAnyPlot(gd);
});
Plotly.newPlot(gd, data, layout);
function runAfterAnyPlot(graphDiv) {
console.log('A plotting pass completed');
}
Attach the listener before calling Plotly.newPlot so the initial pass is observed. Because the event can recur, make the handler idempotent or remove it when it is no longer needed.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Prevent duplicate work
If a later restyle should trigger your code but a particular operation should run only once, guard it explicitly:
Rank #2
let initialized = false;
const gd = document.getElementById('myDiv');
gd.on('plotly_afterplot', () => {
if (!initialized) {
initialized = true;
initializeOnce(gd);
}
updateAfterEachPlot(gd);
});
Plotly.newPlot(gd, data, layout);
Alternatively, keep the one-time action on the newPlot promise and reserve the event for work that genuinely belongs after every pass.
Wait for a static image generated by Plotly
If “image” means a PNG, JPEG or other static export produced by Plotly, first wait for the graph and then await Plotly.toImage. The function returns a promise for an image data URL.
async function createPlotImage() {
const gd = await Plotly.newPlot('myDiv', data, layout);
const imageUrl = await Plotly.toImage(gd, {
format: 'png',
width: 800,
height: 600
});
const img = document.getElementById('exportedImage');
img.src = imageUrl;
// The export URL is now available to your JavaScript.
afterExportCreated(imageUrl);
}
createPlotImage().catch((error) => {
console.error('Plot or export failed', error);
});
The same flow can be written with promise chaining:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Plotly.newPlot('myDiv', data, layout)
.then((gd) => Plotly.toImage(gd, {
format: 'png',
width: 800,
height: 600
}))
.then((imageUrl) => {
document.getElementById('exportedImage').src = imageUrl;
afterExportCreated(imageUrl);
})
.catch((error) => console.error(error));
Plotly’s documented export example demonstrates assigning the resulting URL to an image element. The toImage promise confirms that Plotly has produced the URL; the cited Plotly documentation does not define it as a guarantee that the browser has completed displaying or decoding the eventual <img>.
If you need the browser’s actual image decode milestone
When your code must run after the browser has loaded and decoded the element assigned to src, use the image element’s load/decode APIs in addition to Plotly’s export promise. This is a browser lifecycle step, distinct from Plotly’s documented signals.
Rank #3
async function exportAndWaitForDisplay() {
const gd = await Plotly.newPlot('myDiv', data, layout);
const imageUrl = await Plotly.toImage(gd, {
format: 'png',
width: 800,
height: 600
});
const img = document.getElementById('exportedImage');
img.src = imageUrl;
if (img.complete) {
// Decode if the browser exposes the promise-based API.
if (img.decode) {
await img.decode();
}
} else {
await new Promise((resolve, reject) => {
img.addEventListener('load', resolve, { once: true });
img.addEventListener('error', reject, { once: true });
});
}
runAfterBrowserDecode(img);
}
This extra step is useful for layout measurement or canvas work that depends on decoded pixels. Handle the error path so a failed image does not leave application state waiting forever.
Complete example with the three Plotly paths
<div id="myDiv"></div>
<img id="exportedImage" alt="Static chart export">
<button id="exportButton" disabled>Export PNG</button>
<script>
const data = [{
x: [1, 2, 3, 4],
y: [3, 7, 5, 9],
type: 'scatter',
mode: 'lines+markers'
}];
const layout = { title: 'Example' };
const gd = document.getElementById('myDiv');
// Repeated signal: listen before the first plot.
gd.on('plotly_afterplot', () => {
console.log('Plotting pass complete');
});
// One-time initial-render signal.
Plotly.newPlot(gd, data, layout)
.then((graphDiv) => {
document.getElementById('exportButton').disabled = false;
console.log('Initial plot complete', graphDiv);
})
.catch(console.error);
document.getElementById('exportButton').addEventListener('click', async () => {
try {
const imageUrl = await Plotly.toImage(gd, {
format: 'png',
width: 800,
height: 600
});
const img = document.getElementById('exportedImage');
img.src = imageUrl;
await img.decode();
console.log('Export generated and decoded');
} catch (error) {
console.error('Export failed', error);
}
});
</script>
Common mistakes and fixes
Using setTimeout as a readiness test
A fixed delay does not represent Plotly completion. It may be too short on a busy device and unnecessarily slow on a fast one. Use the newPlot promise, plotly_afterplot, or toImage promise for the milestone you actually need.
Listening after the initial plot
If you register plotly_afterplot after calling Plotly.newPlot, you can miss the first event. Register the handler first.
Expecting plotly_afterplot to fire once
It is a recurring event. Relayout, restyle and other plotting passes can invoke it again. Use a one-time guard or choose the newPlot promise for initialization.
Confusing export generation with display
Plotly.toImage resolves when the export URL is produced. Assigning that URL to img.src starts a separate browser step. Use load or decode() when decoded pixels are required.
Rank #4
Calling toImage before a graph exists
Pass the graph div returned by a completed newPlot call. Await the plot promise before exporting.
Recommended Free Tools
Ignoring rejected promises
Plot creation or export can fail. Add .catch() to promise chains or wrap await calls in try...catch, and report an actionable error in your UI.
Performance and reliability considerations
- Keep recurring
plotly_afterplothandlers lightweight. If they trigger expensive DOM work, debounce that work or move one-time setup to thenewPlotpromise. - Choose export dimensions deliberately. Larger width and height produce more pixels and can require more memory and processing.
- Do not start multiple exports for the same user action without coordinating them; concurrent exports can waste resources and complicate state updates.
- When replacing an image repeatedly, revoke any object URLs you create yourself. A Plotly data URL does not use the same revocation API.
- Keep UI state explicit: disable export controls until the initial plot promise resolves, show a failure state on rejection, and do not treat a timer as proof of readiness.
Or skip the browser setup
If your goal is a clean screenshot or PDF of a finished webpage rather than Plotly lifecycle callbacks inside your own page, ScreenshotNeo provides a single HTTP request. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server supplies take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for request options. The same request in Python is:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
And in Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Features include full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, pre-capture clicks, hidden selectors, selector/delay/network-idle waits, request and resource blocking, custom headers/cookies/user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, selectable cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, usage reporting, an OpenAPI specification and compatible parameter names used by other screenshot APIs.
The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Create a free ScreenshotNeo account to begin.
Best Value
FAQ
Does plotly_afterplot run after a relayout?
Yes. Plotly describes it as firing each time a chart is plotted, including after restyling or relayout.
What does Plotly.toImage return?
It returns a promise that resolves to the exported image data URL.
Can I use the same callback for an interactive graph and an exported image?
No. Use the newPlot promise or plotly_afterplot for chart plotting, then toImage for export generation. Add the image element’s load or decode handling if browser display completion matters.
Frequently Asked Questions
Does plotly_afterplot run after a relayout?
Yes. Plotly describes it as firing each time a chart is plotted, including after restyling or relayout.
What does Plotly.toImage return?
It returns a promise that resolves to the exported image data URL.
Can I use the same callback for an interactive graph and an exported image?
No. Use the newPlot promise or plotly_afterplot for chart plotting, then toImage for export generation. Add the image element’s load or decode handling if browser display completion matters.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.




