New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

limit-once

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

limit-once - npm Package Compare versions

Comparing version 0.7.0 to 0.8.0

21

dist/esm/once-async.js

@@ -1,2 +0,1 @@

import { bind } from "bind-event-listener";
function onceAsync(fn) {

@@ -6,3 +5,2 @@ let state = {

};
let controller = new AbortController();
function cached(...args) {

@@ -15,7 +13,8 @@ if (state.type === "fulfilled") {

}
let rejectPendingPromise;
function abort() {
rejectPendingPromise?.();
}
const promise = new Promise((resolve, reject) => {
function listener() {
reject();
}
const cleanup = bind(controller.signal, { type: "abort", listener: () => reject() });
rejectPendingPromise = reject;
fn.call(this, ...args).then((result) => {

@@ -30,7 +29,8 @@ state = {

reject(...args2);
}).finally(cleanup);
});
});
state = {
type: "pending",
promise
promise,
abort
};

@@ -40,4 +40,5 @@ return promise;

cached.clear = function clear() {
controller.abort();
controller = new AbortController();
if (state.type === "pending") {
state.abort();
}
state = {

@@ -44,0 +45,0 @@ type: "initial"

@@ -13,3 +13,3 @@ {

"license": "MIT",
"version": "0.7.0",
"version": "0.8.0",
"private": false,

@@ -34,5 +34,3 @@ "repository": {

},
"dependencies": {
"bind-event-listener": "^3.0.0"
},
"dependencies": {},
"devDependencies": {

@@ -39,0 +37,0 @@ "@types/bun": "latest",

# limit-once
Create a `once` function that caches the result of the first function call. `limit-once` let's you lazily evaluate a value (using a function), and then hold onto the value forever.
Gives you the ability to ensure a `function` is only called `"once"`, and that that the result of that single `function` call is returned every time.

@@ -10,4 +10,4 @@ > [!NOTE]

- [Synchronous variant](#synchronous-variant) (`150B`)
- [Asynchronous variant for promises](#asynchronous-variant) (`460B`)
- [Synchronous variant](#synchronous-variant) (tiny `150B`)
- [Asynchronous variant for promises](#asynchronous-variant) (tiny `372B`)
- Only include the code for the variant(s) you want

@@ -33,2 +33,4 @@ - Both variants support cache clearing (avoid memory leaks)

Create a new `function` that wraps an existing function, where the wrapped function is only called once.
```ts

@@ -56,2 +58,29 @@ import { once } from 'limit-once';

If the function being wrapped `throw`s an error, then that `throw` is not cached, and the wrapped function is allowed to be called again
```ts
import { once } from 'limit-once';
let callCount = 0;
function maybeThrow({ shouldThrow }: { shouldThrow: boolean }): string {
callCount++;
if (shouldThrow) {
throw new Error(`Call count: ${callCount}`);
}
return `Call count: ${callCount}`;
}
const maybeThrowOnce = once(maybeThrow);
expect(() => maybeThrowOnce({ shouldThrow: true })).toThrowError('Call count: 1');
// failure result was not cached, underlying `maybeThrow` called again
expect(() => maybeThrowOnce({ shouldThrow: true })).toThrowError('Call count: 2');
// our first successful result will be cached
expect(maybeThrowOnce({ shouldThrow: false })).toBe('Call count: 3');
expect(maybeThrowOnce({ shouldThrow: false })).toBe('Call count: 3');
```
### Cache clearing (`.clear()`)

@@ -108,3 +137,3 @@

A "rejected" promise call will not be cached and will allow the wrapped function to be called again
If the wrapped function that returns a promise has it's promise `"rejected"`, then the call will not be cached, and the underlying function can be called again.

@@ -179,3 +208,3 @@ ```ts

If onced async function is `"pending"` when `.clear()` is called, then the promise will be rejected.
If onced async function is `"pending"` when `.clear()` is called, then the promise(s) that the onced function has returned will be rejected.

@@ -192,8 +221,15 @@ ```ts

const promise1 = getNameOnce().catch(() => {
console.log('rejected');
console.log('rejected promise 1');
});
const promise2 = getNameOnce().catch(() => {
console.log('rejected promise 2');
});
// cached cleared while promise was pending
// will cause `promise1` to be rejected
getNameOnce.clear();
// console.log → "rejected promise 1"
// console.log → "rejected promise 2"
```

@@ -1,3 +0,1 @@

import { bind } from 'bind-event-listener';
type ResultValue<TFunc extends (this: any, ...args: any[]) => Promise<any>> = Awaited<

@@ -14,3 +12,3 @@ ReturnType<TFunc>

| { type: 'initial' }
| { type: 'pending'; promise: Promise<T> }
| { type: 'pending'; promise: Promise<T>; abort: () => void }
| { type: 'fulfilled'; result: T };

@@ -27,4 +25,2 @@

let controller = new AbortController();
function cached(

@@ -45,8 +41,9 @@ this: ThisParameterType<TFunc>,

let rejectPendingPromise: (() => void) | null;
function abort() {
rejectPendingPromise?.();
}
const promise: Promise<Result> = new Promise((resolve, reject) => {
function listener() {
reject();
}
const cleanup = bind(controller.signal, { type: 'abort', listener: () => reject() });
rejectPendingPromise = reject;
fn.call(this, ...args)

@@ -64,7 +61,3 @@ .then((result: Result) => {

reject(...args);
})
// this isn't needed for functionality,
// but it seems like a good idea to unbind the event listener
// to prevent possible memory leaks
.finally(cleanup);
});
});

@@ -75,2 +68,3 @@

promise,
abort,
};

@@ -82,6 +76,6 @@

cached.clear = function clear() {
controller.abort();
// Need to create a new controller
// as the old one has been aborted
controller = new AbortController();
if (state.type === 'pending') {
state.abort();
}
state = {

@@ -88,0 +82,0 @@ type: 'initial',

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc