CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-once

Run a function exactly one time

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

Once

Once 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.

Package Information

  • Package Name: once
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install once

Core Imports

var 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.

Basic Usage

var once = require('once');

function load(file, cb) {
  cb = once(cb);
  loader.load('file');
  loader.once('load', cb);
  loader.once('error', cb);
}

Capabilities

Function Wrapping with Caching

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 Function Wrapping

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 execution
  • onceError (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"

Prototype Extension

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();

State Inspection

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 Handling

Standard Once Behavior

  • No errors thrown on multiple calls
  • Silently returns cached value
  • Suitable for callbacks and event handlers

Strict Mode Behavior

  • Throws Error on second and subsequent calls
  • Default error message: "{functionName} shouldn't be called more than once"
  • For anonymous functions: "Function wrapped with \once` shouldn't be called more than once"`
  • Custom error messages supported via 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);
}

Types

/**
 * 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; };
}
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/once@1.4.x
Publish Source
CLI
Badge
tessl/npm-once badge