Run a function exactly one time
npx @tessl/cli install tessl/npm-once@1.4.0Once is a utility library that ensures any given function can only be executed once, returning the cached result of the first execution on subsequent calls. It provides both a regular 'once' wrapper that silently returns the cached value and a 'strict' variant that throws an error on repeated calls, helping developers catch logic errors where functions are accidentally called multiple times.
npm install oncevar once = require('once');Note: This package uses CommonJS format only. ES modules can import it using:
import once from 'once';However, the above may require bundler configuration or Node.js compatibility features.
var once = require('once');
function load(file, cb) {
cb = once(cb);
loader.load('file');
loader.once('load', cb);
loader.once('error', cb);
}Wraps a function to ensure it can only be called once, returning the cached result on subsequent calls.
/**
* Wraps a function to ensure it can only be called once
* @param {Function} fn - The function to wrap
* @returns {Function} Wrapped function with caching behavior and state properties
*/
function once(fn);The returned function has these properties:
called (Boolean): Whether the function has been called (initially false)value (Any): Cached return value from first execution (undefined until called)Important: The wrapped function preserves all original function properties and maintains the original function's this context when called.
Usage Examples:
var once = require('once');
function expensiveOperation(data) {
console.log('Computing...');
return data * 2;
}
var cachedOperation = once(expensiveOperation);
console.log(cachedOperation(5)); // Logs "Computing..." then returns 10
console.log(cachedOperation(5)); // Returns 10 immediately (no logging)
console.log(cachedOperation.called); // true
console.log(cachedOperation.value); // 10
// Property and context preservation example
function Calculator(multiplier) {
this.multiplier = multiplier;
}
Calculator.prototype.compute = function(value) {
return value * this.multiplier;
};
Calculator.prototype.compute.customProperty = 'preserved';
var calc = new Calculator(3);
var onceCompute = once(calc.compute);
// Properties are preserved
console.log(onceCompute.customProperty); // 'preserved'
// Context is preserved when using call/apply
console.log(onceCompute.call(calc, 5)); // 15 (5 * 3)
console.log(onceCompute.call(calc, 10)); // 15 (cached result)Strict variant that throws an error when called more than once, helping catch logic errors.
/**
* Wraps a function to throw an error if called more than once
* @param {Function} fn - The function to wrap
* @returns {Function} Wrapped function that throws on subsequent calls
*/
once.strict(fn);The returned function has these properties:
called (Boolean): Whether the function has been called (initially false)value (Any): Return value from first executiononceError (String): Error message for multiple calls (can be customized)Important: The wrapped function preserves all original function properties and maintains the original function's this context when called.
Usage Examples:
var once = require('once');
function greet(name, cb) {
if (!name) return cb('Hello anonymous');
cb('Hello ' + name);
}
function log(msg) {
console.log(msg);
}
// Using strict mode to catch logic errors
greet(null, once.strict(log));
// First call: logs "Hello anonymous"
// Second call: throws Error: "log shouldn't be called more than once"Custom Error Messages:
var strictFn = once.strict(someFunction);
strictFn.onceError = 'Custom error message';
// Now throws: Error: "Custom error message"Extends Function.prototype with once and onceStrict methods for convenient usage.
/**
* Extends Function.prototype with once and onceStrict methods
* @returns {undefined}
*/
once.proto();After calling once.proto(), all functions gain these methods:
Function.prototype.once(): Returns once(this)Function.prototype.onceStrict(): Returns once.strict(this)Usage Examples:
var once = require('once');
// Enable prototype extension (only needs to be done once)
once.proto();
function load(file, cb) {
cb = cb.once(); // Use prototype method instead of once(cb)
loader.load('file');
loader.once('load', cb);
loader.once('error', cb);
}
// Also works with strict mode
function criticalCallback() {
// Important logic here
}
var safeCriticalCallback = criticalCallback.onceStrict();All wrapped functions provide state inspection capabilities:
// Properties available on wrapped functions:
interface WrappedFunction extends Function {
called: boolean; // Whether function has been executed
value: any; // Cached return value (once variant only)
onceError?: string; // Custom error message (strict variant only)
}Usage Examples:
var once = require('once');
function getData() {
return { data: 'important' };
}
var cachedGetData = once(getData);
// Check if function has been called
if (!cachedGetData.called) {
console.log('Function not yet called');
}
var result = cachedGetData();
console.log(cachedGetData.called); // true
console.log(cachedGetData.value); // { data: 'important' }
// Use in conditional logic
function processData(callback) {
callback = once(callback);
// Do async work...
// Only call callback if not already called
if (!callback.called) {
callback(processedData);
}
}Error on second and subsequent calls"{functionName} shouldn't be called more than once""Function wrapped with \once` shouldn't be called more than once"`onceError property// Error handling example
try {
var strictFn = once.strict(myFunction);
strictFn(); // First call - OK
strictFn(); // Second call - throws Error
} catch (err) {
console.error('Function called multiple times:', err.message);
}/**
* Main once function type
*/
declare function once<T extends Function>(fn: T): T & {
called: boolean;
value: any;
};
/**
* Strict variant type
*/
declare function strict<T extends Function>(fn: T): T & {
called: boolean;
value: any;
onceError: string;
};
/**
* Prototype extension function type
*/
declare function proto(): void;
/**
* Extended Function prototype (after calling once.proto())
*/
interface Function {
once<T extends Function>(this: T): T & { called: boolean; value: any; };
onceStrict<T extends Function>(this: T): T & { called: boolean; value: any; onceError: string; };
}