Using p5.js preload() to Guarantee Asset Availability Before Sketch Starts
Learn how p5.js preload() guarantees that images, sounds, fonts, and data are fully loaded before setup() runs, eliminating race conditions and simplifying asset‑management in creative‑coding sketches.
06 May 2026, 00:45 UTC

Requirements
When a p5.js sketch needs images, sounds, fonts, or data files, the developer must ensure those assets are fully loaded before any drawing logic runs. Without a guarantee, the sketch may attempt to draw a null image, play an undefined sound, or use incomplete data, leading to silent failures or runtime errors.
Smallest Suitable Design
The simplest solution is to place all asset‑loading calls inside the special preload() function. p5.js invokes preload() once, before setup() and draw(), and blocks the sketch lifecycle until every promised load resolves.
let img, sound, font;
function preload() {
img = loadImage('assets/character.png'); // returns p5.Image
sound = loadSound('assets/jump.wav'); // returns p5.SoundFile
font = loadFont('assets/PressStart.ttf'); // returns p5.Font
}
function setup() {
createCanvas(400, 300);
// At this point img, sound, and font are guaranteed to be ready
textFont(font, 24);
}
function draw() {
background(30);
image(img, 50, 50);
if (mouseIsPressed && !sound.isPlaying()) {
sound.play();
}
text('Click to jump', 150, 200);
}
Only the three lines inside preload() are required; no additional libraries or build steps are needed.
Trust/Data Boundaries
Asset loading obeys the browser’s same‑origin policy. If a resource originates from a different domain, the server must send appropriate CORS headers (e.g., Access-Control-Allow-Origin: *) or the request will be blocked and trigger an error event on the corresponding p5.Element. Assets served from the same origin (including localhost during development) load without extra configuration.
Operational Checks
To verify that preload() worked as expected, place a diagnostic check in setup():
function setup() {
createCanvas(200, 200);
if (img) {
console.log('Image loaded:', img.width, 'x', img.height);
} else {
console.warn('Image failed to load');
}
}
Open the browser’s developer console (F12) and confirm the width/height values appear before any drawing occurs. For error cases, deliberately use a 404 URL:
function preload() {
img = loadImage('https://example.com/does-not-exist.png');
}
function setup() {
createCanvas(200, 200);
console.log('img variable:', img); // will be undefined
}
The console will show an error event on the image element, yet setup() still runs, allowing the developer to handle the missing asset gracefully.
Failure Modes
- Network timeout or 4xx/5xx response: The specific
p5.Elementreceives anonErrorcallback; the sketch continues but the variable isnullorundefined. - Cross‑origin block without CORS: The browser aborts the request with a security error; the asset variable remains unset.
- Heavy decoding inside
preload(): Large images or fonts block the main thread, delaying the first frame and potentially causing a sluggish startup.
Conditions That Would Change the Design
If the sketch must start instantly and can tolerate missing assets, developers might move non‑critical loads into setup() or use lazy‑loading with callbacks/promises. For very large asset bundles, splitting loads across multiple preload() calls or employing a Web Worker to decode data off the main thread can mitigate startup latency. Conversely, if the project requires guaranteed availability of all resources before any interaction, keeping every load inside a single preload() remains the smallest reliable design.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.