Skip to content

Commit d2351db

Browse files
authored
feat: pass scope as this in withLock (#1)
1 parent f93fbd0 commit d2351db

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-7
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ const res = await Promise.all([
4949
console.log(res); // [42, 42, 42]
5050
```
5151

52+
53+
The given `scope` is used as the callback's `this`, so you can use its value in a `function`:
54+
55+
```typescript
56+
import {withLock} from "lifecycle-utils";
57+
58+
const scope = {userName: "Joe"}; // can be a reference to any object you like
59+
60+
const res = await withLock(scope, "myKey", async function () {
61+
await new Promise(resolve => setTimeout(resolve, 1000));
62+
return `Hello ${this.userName}`;
63+
});
64+
65+
console.log(res); // Hello Joe
66+
```
67+
5268
### `isLockActive`
5369
Check whether a lock is currently active for the given `scope` and `key`.
5470

src/withLock.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ const locks = new Map<any, Map<string, Promise<any>>>();
33
/**
44
* Only allow one instance of the callback to run at a time for a given `scope` and `key`.
55
*/
6-
export async function withLock<ReturnType>(scope: any, key: string, callback: () => Promise<ReturnType>): Promise<ReturnType>;
7-
export async function withLock<ReturnType>(
8-
scope: any, key: string, acquireLockSignal: AbortSignal | undefined, callback: () => Promise<ReturnType>
6+
export async function withLock<ReturnType, const ScopeType = any>(
7+
scope: ScopeType, key: string, callback: (this: ScopeType) => Promise<ReturnType>
98
): Promise<ReturnType>;
10-
export async function withLock<ReturnType>(
11-
scope: any,
9+
export async function withLock<ReturnType, const ScopeType = any>(
10+
scope: ScopeType, key: string, acquireLockSignal: AbortSignal | undefined, callback: (this: ScopeType) => Promise<ReturnType>
11+
): Promise<ReturnType>;
12+
export async function withLock<ReturnType, const ScopeType = any>(
13+
scope: ScopeType,
1214
key: string,
13-
acquireLockSignalOrCallback: AbortSignal | undefined | (() => Promise<ReturnType>),
15+
acquireLockSignalOrCallback: AbortSignal | undefined | ((this: ScopeType) => Promise<ReturnType>),
1416
callback?: () => Promise<ReturnType>
1517
): Promise<ReturnType> {
1618
let acquireLockSignal: AbortSignal | undefined = undefined;
@@ -47,7 +49,7 @@ export async function withLock<ReturnType>(
4749
throw acquireLockSignal.reason;
4850
}
4951

50-
const promise = callback();
52+
const promise = callback.call(scope);
5153

5254
if (!locks.has(scope))
5355
locks.set(scope, new Map());

test/withLock.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,18 @@ describe("withLock", () => {
300300
// do nothing
301301
}
302302
});
303+
304+
test("this scope works", async () => {
305+
const scope = {data: 1};
306+
const key = "key";
307+
308+
let calls = 0;
309+
await withLock(scope, key, async function (){
310+
expect(this).toBe(scope);
311+
calls++;
312+
});
313+
expect(calls).toBe(1);
314+
});
303315
});
304316

305317

0 commit comments

Comments
 (0)