diff --git a/lib/addons/p5.sound.js b/lib/addons/p5.sound.js index 761a42ff2f..f1fb294426 100644 --- a/lib/addons/p5.sound.js +++ b/lib/addons/p5.sound.js @@ -2945,11 +2945,10 @@ function () { }(); /** * loadSound() returns a new p5.SoundFile from a specified - * path. If called during preload(), the p5.SoundFile will be ready - * to play in time for setup() and draw(). If called outside of - * preload, the p5.SoundFile will not be ready immediately, so - * loadSound accepts a callback as the second parameter. Using a - * + * path. If used with asynchronous setup (via `async`/`await`), the p5.SoundFile + * will be ready to play in time for `setup()` and `draw()`. If called outside of an async context, + * the p5.SoundFile will not be ready immediately, so loadSound accepts a callback as the second + * parameter. Using a * local server is recommended when loading external files. * * @method loadSound diff --git a/src/core/main.js b/src/core/main.js index 3394715aa2..4777d11dc6 100644 --- a/src/core/main.js +++ b/src/core/main.js @@ -14,9 +14,10 @@ import * as constants from './constants'; * a p5 sketch. It expects an incoming sketch closure and it can also * take an optional node parameter for attaching the generated p5 canvas * to a node. The sketch closure takes the newly created p5 instance as - * its sole argument and may optionally set preload(), - * setup(), and/or - * draw() properties on it for running a sketch. + * its sole argument and may optionally set an asynchronous function + * using `async/await`, along with the standard setup(), + * and/or setup(), and/or draw() + * properties on it for running a sketch. * * A p5 sketch can run in "global" or "instance" mode: * "global" - all properties and methods are attached to the window @@ -465,6 +466,8 @@ for (const k in constants) { * draw() begins looping. If the * preload() is declared, then `setup()` will * run immediately after preload() finishes + * + * * loading assets. * * Note: `setup()` doesn’t have to be declared, but it’s common practice to do so. diff --git a/src/core/reference.js b/src/core/reference.js index 3ee337f7f8..c830ac5eaf 100644 --- a/src/core/reference.js +++ b/src/core/reference.js @@ -1137,6 +1137,115 @@ * */ + +/** + * Asynchronous Asset Loading with Async/Await. + * + * The keywords `async` and `await` let you write asynchronous code in a more + * straightforward, linear style. Instead of nesting callbacks or juggling + * multiple promise chains, you can pause execution at `await` while waiting + * for a promise to resolve. This makes your code flow more naturally, as if + * it were synchronous. + * + * When you mark a function with the `async` keyword—like `async function setup() {...}`—it + * signals that the function contains asynchronous operations and will return a + * promise. Any time you use the `await` keyword inside this function, JavaScript + * will pause the function’s execution until the awaited promise settles. + * + * In p5.js, you can use `async/await` to handle media loading functions such as + * `loadImage()`, `loadJSON()`, `loadSound()`, and so on. This allows you to: + * - load files in a more readable, top-to-bottom manner + * - decide when the assets are fully available before proceeding + * + * Nested callbacks require managing additional information and behavior. + * Lazy loading of assets with `async/await` can simplify control flow, + * but it also requires you to design your sketch around waiting for + * each operation to complete. + * + * Callbacks are still fully supported, so code that passes success / error + * functions to loaders like `loadImage()` or `loadJSON()` will behave exactly + * as it always has. This compatibility means sketches written with the older + * pattern don’t need any changes, and you can freely mix callbacks and + * `async/await` in the same project if that suits your workflow. + * + * In the example below, `setup()` is declared as an async function. We `await` + * the completion of both `loadImage()` and `loadJSON()` before calling + * `createCanvas()`. Only then does the sketch proceed, guaranteeing the assets + * are available for immediate use. + * + * ```js + * let img, data; + * + * async function setup() { + * // Wait until the image and JSON data have fully loaded. + * img = await loadImage("./my-image.png"); + * data = await loadJSON("./my-data.json"); + * + * // Once the assets are loaded, create the canvas. + * createCanvas(400, 400); + * } + * ``` + * + * @property async_await + * @example + *
+ * // Click and drag the mouse to view the scene from different angles.
+ *
+ * let shape;
+ *
+ * // Load the file and create a p5.Geometry object.
+ * async function setup() {
+ * shape = await loadModel('/assets/teapot.obj');
+ *
+ * createCanvas(100, 100, WEBGL);
+ *
+ * describe('A white teapot drawn against a gray background.');
+ * }
+ *
+ * function draw() {
+ * background(200);
+ *
+ * // Enable orbiting with the mouse.
+ * orbitControl();
+ *
+ * // Draw the shape.
+ * model(shape);
+ * }
+ *
+ *
+ * let font;
+ *
+ * async function setup() {
+ * // Load a font for WebGL mode.
+ * font = await loadFont('assets/inconsolata.otf');
+ *
+ * createCanvas(100, 100, WEBGL);
+ *
+ * describe(
+ * "A gray square. The mouse's x- and y-coordinates are displayed as the user moves the mouse."
+ * );
+ * }
+ *
+ * function draw() {
+ * background(200);
+ *
+ * // Style the text.
+ * textAlign(CENTER);
+ * textSize(16);
+ * textFont(font);
+ * fill(0);
+ *
+ * // Display the mouse's coordinates.
+ * text(`x: ${mouseX} y: ${mouseY}`, 0, 0);
+ * }
+ *
+ *