Skip to content

Commit 77676c4

Browse files
committed
♻️ [util] 新增func_lazy
1 parent 5026592 commit 77676c4

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

util/deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@gaubee/util",
3-
"version": "0.24.1",
3+
"version": "0.25.0",
44
"exports": {
55
"./abort": "./src/abort.ts",
66
"./bigint": "./src/bigint.ts",

util/src/func.test.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { func_catch, func_remember } from "./func.ts";
1+
import { func_catch, func_lazy, func_remember } from "./func.ts";
22
import assert from "node:assert";
33

44
Deno.test("func_remember", async () => {
@@ -34,3 +34,43 @@ Deno.test("func_catch", async () => {
3434
assert.deepEqual(await fn3(1, "2"), [undefined, `async 1+2`]);
3535
assert.deepEqual(await fn4(1, "2"), [`async 1+2`, undefined]);
3636
});
37+
38+
Deno.test("func_lazy", () => {
39+
let factoryCallCount = 0;
40+
41+
const lazyFn = func_lazy(() => {
42+
factoryCallCount++;
43+
return (x: number) => x * 2;
44+
});
45+
46+
// Factory should not be called until first use
47+
assert.equal(factoryCallCount, 0);
48+
49+
// First call should create the function
50+
assert.equal(lazyFn(5), 10);
51+
assert.equal(factoryCallCount, 1);
52+
53+
// Subsequent calls should reuse the same function
54+
assert.equal(lazyFn(7), 14);
55+
assert.equal(factoryCallCount, 1);
56+
});
57+
58+
Deno.test("func_lazy with this context", () => {
59+
let factoryCallCount = 0;
60+
61+
const lazyFn = func_lazy(() => {
62+
factoryCallCount++;
63+
return function (this: { multiplier: number }, x: number) {
64+
return x * this.multiplier;
65+
};
66+
});
67+
const obj = { multiplier: 3, fn: lazyFn };
68+
69+
// Test with this context
70+
assert.equal(obj.fn(5), 15);
71+
assert.equal(factoryCallCount, 1);
72+
73+
// Should reuse the same function
74+
assert.equal(obj.fn(7), 21);
75+
assert.equal(factoryCallCount, 1);
76+
});

util/src/func.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,15 @@ export const func_catch: FuncCatch = Object.assign(
251251
wrapError,
252252
},
253253
);
254+
255+
export const func_lazy = <T extends Func>(factory: Func.SetReturn<T, T>): T => {
256+
let fn: T | undefined;
257+
return new Proxy(factory as unknown as T, {
258+
apply(_, thisArg, argArray) {
259+
if (fn == undefined) {
260+
fn = Reflect.apply(factory, thisArg, argArray);
261+
}
262+
return Reflect.apply(fn!, thisArg, argArray);
263+
},
264+
});
265+
};

0 commit comments

Comments
 (0)