Run a function exactly one time
npx @tessl/cli install tessl/npm-once@1.4.00
# Once
1
2
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.
3
4
## Package Information
5
6
- **Package Name**: once
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install once`
10
11
## Core Imports
12
13
```javascript
14
var once = require('once');
15
```
16
17
**Note**: This package uses CommonJS format only. ES modules can import it using:
18
19
```javascript
20
import once from 'once';
21
```
22
23
However, the above may require bundler configuration or Node.js compatibility features.
24
25
## Basic Usage
26
27
```javascript
28
var once = require('once');
29
30
function load(file, cb) {
31
cb = once(cb);
32
loader.load('file');
33
loader.once('load', cb);
34
loader.once('error', cb);
35
}
36
```
37
38
## Capabilities
39
40
### Function Wrapping with Caching
41
42
Wraps a function to ensure it can only be called once, returning the cached result on subsequent calls.
43
44
```javascript { .api }
45
/**
46
* Wraps a function to ensure it can only be called once
47
* @param {Function} fn - The function to wrap
48
* @returns {Function} Wrapped function with caching behavior and state properties
49
*/
50
function once(fn);
51
```
52
53
The returned function has these properties:
54
- `called` (Boolean): Whether the function has been called (initially false)
55
- `value` (Any): Cached return value from first execution (undefined until called)
56
57
**Important:** The wrapped function preserves all original function properties and maintains the original function's `this` context when called.
58
59
**Usage Examples:**
60
61
```javascript
62
var once = require('once');
63
64
function expensiveOperation(data) {
65
console.log('Computing...');
66
return data * 2;
67
}
68
69
var cachedOperation = once(expensiveOperation);
70
71
console.log(cachedOperation(5)); // Logs "Computing..." then returns 10
72
console.log(cachedOperation(5)); // Returns 10 immediately (no logging)
73
console.log(cachedOperation.called); // true
74
console.log(cachedOperation.value); // 10
75
76
// Property and context preservation example
77
function Calculator(multiplier) {
78
this.multiplier = multiplier;
79
}
80
81
Calculator.prototype.compute = function(value) {
82
return value * this.multiplier;
83
};
84
85
Calculator.prototype.compute.customProperty = 'preserved';
86
87
var calc = new Calculator(3);
88
var onceCompute = once(calc.compute);
89
90
// Properties are preserved
91
console.log(onceCompute.customProperty); // 'preserved'
92
93
// Context is preserved when using call/apply
94
console.log(onceCompute.call(calc, 5)); // 15 (5 * 3)
95
console.log(onceCompute.call(calc, 10)); // 15 (cached result)
96
```
97
98
### Strict Function Wrapping
99
100
Strict variant that throws an error when called more than once, helping catch logic errors.
101
102
```javascript { .api }
103
/**
104
* Wraps a function to throw an error if called more than once
105
* @param {Function} fn - The function to wrap
106
* @returns {Function} Wrapped function that throws on subsequent calls
107
*/
108
once.strict(fn);
109
```
110
111
The returned function has these properties:
112
- `called` (Boolean): Whether the function has been called (initially false)
113
- `value` (Any): Return value from first execution
114
- `onceError` (String): Error message for multiple calls (can be customized)
115
116
**Important:** The wrapped function preserves all original function properties and maintains the original function's `this` context when called.
117
118
**Usage Examples:**
119
120
```javascript
121
var once = require('once');
122
123
function greet(name, cb) {
124
if (!name) return cb('Hello anonymous');
125
cb('Hello ' + name);
126
}
127
128
function log(msg) {
129
console.log(msg);
130
}
131
132
// Using strict mode to catch logic errors
133
greet(null, once.strict(log));
134
// First call: logs "Hello anonymous"
135
// Second call: throws Error: "log shouldn't be called more than once"
136
```
137
138
**Custom Error Messages:**
139
140
```javascript
141
var strictFn = once.strict(someFunction);
142
strictFn.onceError = 'Custom error message';
143
// Now throws: Error: "Custom error message"
144
```
145
146
### Prototype Extension
147
148
Extends Function.prototype with `once` and `onceStrict` methods for convenient usage.
149
150
```javascript { .api }
151
/**
152
* Extends Function.prototype with once and onceStrict methods
153
* @returns {undefined}
154
*/
155
once.proto();
156
```
157
158
After calling `once.proto()`, all functions gain these methods:
159
- `Function.prototype.once()`: Returns `once(this)`
160
- `Function.prototype.onceStrict()`: Returns `once.strict(this)`
161
162
**Usage Examples:**
163
164
```javascript
165
var once = require('once');
166
167
// Enable prototype extension (only needs to be done once)
168
once.proto();
169
170
function load(file, cb) {
171
cb = cb.once(); // Use prototype method instead of once(cb)
172
loader.load('file');
173
loader.once('load', cb);
174
loader.once('error', cb);
175
}
176
177
// Also works with strict mode
178
function criticalCallback() {
179
// Important logic here
180
}
181
182
var safeCriticalCallback = criticalCallback.onceStrict();
183
```
184
185
## State Inspection
186
187
All wrapped functions provide state inspection capabilities:
188
189
```javascript { .api }
190
// Properties available on wrapped functions:
191
interface WrappedFunction extends Function {
192
called: boolean; // Whether function has been executed
193
value: any; // Cached return value (once variant only)
194
onceError?: string; // Custom error message (strict variant only)
195
}
196
```
197
198
**Usage Examples:**
199
200
```javascript
201
var once = require('once');
202
203
function getData() {
204
return { data: 'important' };
205
}
206
207
var cachedGetData = once(getData);
208
209
// Check if function has been called
210
if (!cachedGetData.called) {
211
console.log('Function not yet called');
212
}
213
214
var result = cachedGetData();
215
console.log(cachedGetData.called); // true
216
console.log(cachedGetData.value); // { data: 'important' }
217
218
// Use in conditional logic
219
function processData(callback) {
220
callback = once(callback);
221
222
// Do async work...
223
224
// Only call callback if not already called
225
if (!callback.called) {
226
callback(processedData);
227
}
228
}
229
```
230
231
## Error Handling
232
233
### Standard Once Behavior
234
- No errors thrown on multiple calls
235
- Silently returns cached value
236
- Suitable for callbacks and event handlers
237
238
### Strict Mode Behavior
239
- Throws `Error` on second and subsequent calls
240
- Default error message: `"{functionName} shouldn't be called more than once"`
241
- For anonymous functions: `"Function wrapped with \`once\` shouldn't be called more than once"`
242
- Custom error messages supported via `onceError` property
243
244
```javascript
245
// Error handling example
246
try {
247
var strictFn = once.strict(myFunction);
248
strictFn(); // First call - OK
249
strictFn(); // Second call - throws Error
250
} catch (err) {
251
console.error('Function called multiple times:', err.message);
252
}
253
```
254
255
## Types
256
257
```javascript { .api }
258
/**
259
* Main once function type
260
*/
261
declare function once<T extends Function>(fn: T): T & {
262
called: boolean;
263
value: any;
264
};
265
266
/**
267
* Strict variant type
268
*/
269
declare function strict<T extends Function>(fn: T): T & {
270
called: boolean;
271
value: any;
272
onceError: string;
273
};
274
275
/**
276
* Prototype extension function type
277
*/
278
declare function proto(): void;
279
280
/**
281
* Extended Function prototype (after calling once.proto())
282
*/
283
interface Function {
284
once<T extends Function>(this: T): T & { called: boolean; value: any; };
285
onceStrict<T extends Function>(this: T): T & { called: boolean; value: any; onceError: string; };
286
}
287
```