Understanding the jQuery Callbacks Once Flag

The $.Callbacks() utility in jQuery provides a multi-purpose tool for managing callback functions, allowing developers to queue, fire, and manage custom functions efficiently. When the 'once' flag is passed during initialization, it fundamentally alters the callback list by ensuring that the callbacks can only be executed a single time, preventing any subsequent firing of the list.

Single Execution Behavior

By default, a standard jQuery Callbacks list can be fired repeatedly. Every time .fire() or .fireWith() is invoked, all attached functions run sequentially. When the 'once' flag is supplied ($.Callbacks('once')), the list executes only on the first call to .fire(). Any subsequent calls to .fire() are completely ignored, and the callbacks will not run again.

let callbacks = $.Callbacks('once');

callbacks.add(function(val) {
    console.log("Triggered:", val);
});

callbacks.fire("First call");  // Logs: "Triggered: First call"
callbacks.fire("Second call"); // Ignored: does nothing

Handling Late Additions

When using only the 'once' flag without the 'memory' flag, any function added using .add() after the list has already fired will not be executed. Because the list has completed its single allowed run, new functions simply remain uncalled unless the callback object is configured with complementary flags.

Combining 'once' with the 'memory' Flag

The 'once' flag is frequently paired with the 'memory' flag ($.Callbacks('once memory')). This specific combination enables a unique behavior:

  • The list as a whole can still only be manually triggered via .fire() once.
  • Any callbacks added via .add() after the initial firing will be executed immediately using the arguments supplied during that initial fire event.

This pattern is the foundational mechanism behind jQuery's $.Deferred() and Promise implementations, where an operation resolves only once, but any handlers registered after resolution must still execute with the original resolved values.

Memory Management and State

Once fired, an isolated 'once' callback list essentially locks its state. The .fired() method will permanently return true. Internally, jQuery tears down and clears the callback list after execution to free up memory resources, preventing detached function references from lingering in memory.