@zk-tech/bedrock 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/array/index.cjs +22 -0
- package/dist/array/index.cjs.map +1 -0
- package/dist/array/index.d.cts +13 -0
- package/dist/array/index.d.ts +13 -0
- package/dist/array/index.js +19 -0
- package/dist/array/index.js.map +1 -0
- package/dist/assert/index.cjs +29 -0
- package/dist/assert/index.cjs.map +1 -0
- package/dist/assert/index.d.cts +25 -0
- package/dist/assert/index.d.ts +25 -0
- package/dist/assert/index.js +24 -0
- package/dist/assert/index.js.map +1 -0
- package/dist/async/index.cjs +746 -0
- package/dist/async/index.cjs.map +1 -0
- package/dist/async/index.d.cts +47 -0
- package/dist/async/index.d.ts +47 -0
- package/dist/async/index.js +738 -0
- package/dist/async/index.js.map +1 -0
- package/dist/barrier-316Xonfd.d.cts +18 -0
- package/dist/barrier-316Xonfd.d.ts +18 -0
- package/dist/byte/index.cjs +59 -0
- package/dist/byte/index.cjs.map +1 -0
- package/dist/byte/index.d.cts +12 -0
- package/dist/byte/index.d.ts +12 -0
- package/dist/byte/index.js +49 -0
- package/dist/byte/index.js.map +1 -0
- package/dist/cache/index.cjs +418 -0
- package/dist/cache/index.cjs.map +1 -0
- package/dist/cache/index.d.cts +40 -0
- package/dist/cache/index.d.ts +40 -0
- package/dist/cache/index.js +415 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cancellation-BIIv2UJm.d.cts +25 -0
- package/dist/cancellation-ClqPPsV1.d.ts +25 -0
- package/dist/context/index.cjs +59 -0
- package/dist/context/index.cjs.map +1 -0
- package/dist/context/index.d.cts +33 -0
- package/dist/context/index.d.ts +33 -0
- package/dist/context/index.js +51 -0
- package/dist/context/index.js.map +1 -0
- package/dist/di/index.cjs +1965 -0
- package/dist/di/index.cjs.map +1 -0
- package/dist/di/index.d.cts +140 -0
- package/dist/di/index.d.ts +140 -0
- package/dist/di/index.js +1949 -0
- package/dist/di/index.js.map +1 -0
- package/dist/disposable-t-B15Nu57y.d.ts +93 -0
- package/dist/disposable-t-CVsiyHPL.d.cts +93 -0
- package/dist/dispose/index.cjs +356 -0
- package/dist/dispose/index.cjs.map +1 -0
- package/dist/dispose/index.d.cts +26 -0
- package/dist/dispose/index.d.ts +26 -0
- package/dist/dispose/index.js +340 -0
- package/dist/dispose/index.js.map +1 -0
- package/dist/dispose-base-CAeXDpjg.d.cts +6 -0
- package/dist/dispose-base-CAeXDpjg.d.ts +6 -0
- package/dist/emitter-CAfCtSTg.d.cts +35 -0
- package/dist/emitter-DeM5mlEm.d.ts +35 -0
- package/dist/error/index.cjs +145 -0
- package/dist/error/index.cjs.map +1 -0
- package/dist/error/index.d.cts +45 -0
- package/dist/error/index.d.ts +45 -0
- package/dist/error/index.js +126 -0
- package/dist/error/index.js.map +1 -0
- package/dist/error-base-B4zaiJ5m.d.cts +32 -0
- package/dist/error-base-B4zaiJ5m.d.ts +32 -0
- package/dist/event/index.cjs +550 -0
- package/dist/event/index.cjs.map +1 -0
- package/dist/event/index.d.cts +139 -0
- package/dist/event/index.d.ts +139 -0
- package/dist/event/index.js +538 -0
- package/dist/event/index.js.map +1 -0
- package/dist/function/index.cjs +132 -0
- package/dist/function/index.cjs.map +1 -0
- package/dist/function/index.d.cts +26 -0
- package/dist/function/index.d.ts +26 -0
- package/dist/function/index.js +129 -0
- package/dist/function/index.js.map +1 -0
- package/dist/graph-BGbNOniY.d.cts +23 -0
- package/dist/graph-BGbNOniY.d.ts +23 -0
- package/dist/hash/index.cjs +54 -0
- package/dist/hash/index.cjs.map +1 -0
- package/dist/hash/index.d.cts +5 -0
- package/dist/hash/index.d.ts +5 -0
- package/dist/hash/index.js +50 -0
- package/dist/hash/index.js.map +1 -0
- package/dist/instantiation-service.interface-CVFMBUUD.d.cts +78 -0
- package/dist/instantiation-service.interface-CVFMBUUD.d.ts +78 -0
- package/dist/json/index.cjs +28 -0
- package/dist/json/index.cjs.map +1 -0
- package/dist/json/index.d.cts +8 -0
- package/dist/json/index.d.ts +8 -0
- package/dist/json/index.js +26 -0
- package/dist/json/index.js.map +1 -0
- package/dist/launch/index.cjs +213 -0
- package/dist/launch/index.cjs.map +1 -0
- package/dist/launch/index.d.cts +46 -0
- package/dist/launch/index.d.ts +46 -0
- package/dist/launch/index.js +211 -0
- package/dist/launch/index.js.map +1 -0
- package/dist/linked-list-CUkue5DZ.d.cts +24 -0
- package/dist/linked-list-CUkue5DZ.d.ts +24 -0
- package/dist/lock/index.cjs +662 -0
- package/dist/lock/index.cjs.map +1 -0
- package/dist/lock/index.d.cts +145 -0
- package/dist/lock/index.d.ts +145 -0
- package/dist/lock/index.js +656 -0
- package/dist/lock/index.js.map +1 -0
- package/dist/lodash-es/index.cjs +14 -0
- package/dist/lodash-es/index.cjs.map +1 -0
- package/dist/lodash-es/index.d.cts +1 -0
- package/dist/lodash-es/index.d.ts +1 -0
- package/dist/lodash-es/index.js +3 -0
- package/dist/lodash-es/index.js.map +1 -0
- package/dist/math/index.cjs +161 -0
- package/dist/math/index.cjs.map +1 -0
- package/dist/math/index.d.cts +76 -0
- package/dist/math/index.d.ts +76 -0
- package/dist/math/index.js +156 -0
- package/dist/math/index.js.map +1 -0
- package/dist/network/index.cjs +91 -0
- package/dist/network/index.cjs.map +1 -0
- package/dist/network/index.d.cts +62 -0
- package/dist/network/index.d.ts +62 -0
- package/dist/network/index.js +82 -0
- package/dist/network/index.js.map +1 -0
- package/dist/objects/index.cjs +80 -0
- package/dist/objects/index.cjs.map +1 -0
- package/dist/objects/index.d.cts +11 -0
- package/dist/objects/index.d.ts +11 -0
- package/dist/objects/index.js +77 -0
- package/dist/objects/index.js.map +1 -0
- package/dist/platform/index.cjs +62 -0
- package/dist/platform/index.cjs.map +1 -0
- package/dist/platform/index.d.cts +21 -0
- package/dist/platform/index.d.ts +21 -0
- package/dist/platform/index.js +48 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/promise/index.cjs +639 -0
- package/dist/promise/index.cjs.map +1 -0
- package/dist/promise/index.d.cts +63 -0
- package/dist/promise/index.d.ts +63 -0
- package/dist/promise/index.js +633 -0
- package/dist/promise/index.js.map +1 -0
- package/dist/scheduler/index.cjs +599 -0
- package/dist/scheduler/index.cjs.map +1 -0
- package/dist/scheduler/index.d.cts +57 -0
- package/dist/scheduler/index.d.ts +57 -0
- package/dist/scheduler/index.js +594 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/sprintf/index.cjs +101 -0
- package/dist/sprintf/index.cjs.map +1 -0
- package/dist/sprintf/index.d.cts +3 -0
- package/dist/sprintf/index.d.ts +3 -0
- package/dist/sprintf/index.js +99 -0
- package/dist/sprintf/index.js.map +1 -0
- package/dist/structure/index.cjs +300 -0
- package/dist/structure/index.cjs.map +1 -0
- package/dist/structure/index.d.cts +21 -0
- package/dist/structure/index.d.ts +21 -0
- package/dist/structure/index.js +296 -0
- package/dist/structure/index.js.map +1 -0
- package/dist/type/index.cjs +4 -0
- package/dist/type/index.cjs.map +1 -0
- package/dist/type/index.d.cts +20 -0
- package/dist/type/index.d.ts +20 -0
- package/dist/type/index.js +3 -0
- package/dist/type/index.js.map +1 -0
- package/dist/undo-redo-stack/index.cjs +545 -0
- package/dist/undo-redo-stack/index.cjs.map +1 -0
- package/dist/undo-redo-stack/index.d.cts +130 -0
- package/dist/undo-redo-stack/index.d.ts +130 -0
- package/dist/undo-redo-stack/index.js +542 -0
- package/dist/undo-redo-stack/index.js.map +1 -0
- package/dist/uuid/index.cjs +67 -0
- package/dist/uuid/index.cjs.map +1 -0
- package/dist/uuid/index.d.cts +17 -0
- package/dist/uuid/index.d.ts +17 -0
- package/dist/uuid/index.js +61 -0
- package/dist/uuid/index.js.map +1 -0
- package/dist/worker/index.cjs +271 -0
- package/dist/worker/index.cjs.map +1 -0
- package/dist/worker/index.d.cts +66 -0
- package/dist/worker/index.d.ts +66 -0
- package/dist/worker/index.js +267 -0
- package/dist/worker/index.js.map +1 -0
- package/package.json +285 -0
- package/src/_internal/logger.ts +59 -0
- package/src/array/array.test.ts +35 -0
- package/src/array/array.ts +25 -0
- package/src/array/index.ts +1 -0
- package/src/assert/assert.test.ts +86 -0
- package/src/assert/assert.ts +42 -0
- package/src/assert/index.ts +2 -0
- package/src/async/barrier.test.ts +90 -0
- package/src/async/barrier.ts +58 -0
- package/src/async/cancellation.test.ts +85 -0
- package/src/async/cancellation.ts +193 -0
- package/src/async/index.ts +18 -0
- package/src/async/queue/queue.test.ts +70 -0
- package/src/async/queue/queue.ts +56 -0
- package/src/async/queue/task.test.ts +155 -0
- package/src/async/queue/task.ts +67 -0
- package/src/async/utils.test.ts +28 -0
- package/src/async/utils.ts +8 -0
- package/src/async/wait.ts +9 -0
- package/src/byte/format.test.ts +64 -0
- package/src/byte/format.ts +44 -0
- package/src/byte/index.ts +2 -0
- package/src/byte/node_modules/.vitest/results.json +1 -0
- package/src/byte/var.ts +11 -0
- package/src/cache/index.ts +2 -0
- package/src/cache/lru-with-timeout.test.ts +88 -0
- package/src/cache/lru-with-timeout.ts +85 -0
- package/src/cache/lru.test.ts +56 -0
- package/src/cache/lru.ts +59 -0
- package/src/context/context.test.ts +17 -0
- package/src/context/context.ts +60 -0
- package/src/context/index.ts +8 -0
- package/src/di/base.ts +73 -0
- package/src/di/container-service.test.ts +179 -0
- package/src/di/context.web.tsx +41 -0
- package/src/di/descriptor.ts +31 -0
- package/src/di/idle-value.test.ts +73 -0
- package/src/di/idle-value.ts +63 -0
- package/src/di/index.common.ts +32 -0
- package/src/di/index.ts +2 -0
- package/src/di/instantiation-service.interface.ts +46 -0
- package/src/di/instantiation-service.test.ts +337 -0
- package/src/di/instantiation-service.ts +468 -0
- package/src/di/lazy/foo.mock.ts +28 -0
- package/src/di/lazy/idle-load.ts +39 -0
- package/src/di/lazy/index.ts +4 -0
- package/src/di/lazy/lazy-service.test.ts +65 -0
- package/src/di/lazy/lazy-service.ts +71 -0
- package/src/di/lazy/type.ts +5 -0
- package/src/di/node_modules/.vitest/results.json +1 -0
- package/src/di/proxy-builder.test.ts +45 -0
- package/src/di/proxy-builder.ts +38 -0
- package/src/di/service-collection.test.ts +27 -0
- package/src/di/service-collection.ts +46 -0
- package/src/di/service-ownership-collection.test.ts +39 -0
- package/src/di/service-ownership-collection.ts +38 -0
- package/src/di/service-registry.test.ts +66 -0
- package/src/di/service-registry.ts +99 -0
- package/src/di/trace.ts +85 -0
- package/src/dispose/disposable-store.test.ts +57 -0
- package/src/dispose/disposable-store.ts +80 -0
- package/src/dispose/disposable-t.test.ts +123 -0
- package/src/dispose/disposable-t.ts +238 -0
- package/src/dispose/disposable-utils.test.ts +15 -0
- package/src/dispose/disposable-utils.ts +28 -0
- package/src/dispose/dispose-base.ts +9 -0
- package/src/dispose/index.ts +34 -0
- package/src/dispose/logger.test.ts +65 -0
- package/src/dispose/logger.ts +39 -0
- package/src/dispose/timer.test.ts +30 -0
- package/src/dispose/timer.ts +16 -0
- package/src/dispose/tracker.test.ts +51 -0
- package/src/dispose/tracker.ts +105 -0
- package/src/error/error-base.ts +45 -0
- package/src/error/error-code.ts +39 -0
- package/src/error/error-const.test.ts +30 -0
- package/src/error/error-const.ts +16 -0
- package/src/error/error-or.test.ts +44 -0
- package/src/error/error-or.ts +2 -0
- package/src/error/error-t.test.ts +116 -0
- package/src/error/error-t.ts +100 -0
- package/src/error/index.ts +24 -0
- package/src/error/node_modules/.vitest/results.json +1 -0
- package/src/event/disposable-linked-list.ts +29 -0
- package/src/event/emitter.test.ts +191 -0
- package/src/event/emitter.ts +162 -0
- package/src/event/error-handler.ts +22 -0
- package/src/event/index.ts +34 -0
- package/src/event/once.ts +29 -0
- package/src/event/phase-emitter.test.ts +212 -0
- package/src/event/phase-emitter.ts +209 -0
- package/src/event/shortcut-event-utils.ts +33 -0
- package/src/event/utils.ts +6 -0
- package/src/event/when.ts +40 -0
- package/src/function/debounce.test.ts +274 -0
- package/src/function/debounce.ts +168 -0
- package/src/function/index.ts +2 -0
- package/src/function/node_modules/.vitest/results.json +1 -0
- package/src/function/throttle.test.ts +179 -0
- package/src/function/throttle.ts +26 -0
- package/src/hash/hash-t.test.ts +100 -0
- package/src/hash/hash-t.ts +51 -0
- package/src/hash/index.ts +3 -0
- package/src/json/index.ts +1 -0
- package/src/json/node_modules/.vitest/results.json +1 -0
- package/src/json/parse.ts +19 -0
- package/src/launch/abstract-job.ts +45 -0
- package/src/launch/cost-recorder.ts +22 -0
- package/src/launch/index.ts +2 -0
- package/src/launch/job-scheduler.test.ts +122 -0
- package/src/launch/job-scheduler.ts +118 -0
- package/src/launch/node_modules/.vitest/deps/_metadata.json +8 -0
- package/src/launch/node_modules/.vitest/deps/package.json +3 -0
- package/src/launch/node_modules/.vitest/results.json +1 -0
- package/src/lock/README.md +11 -0
- package/src/lock/capability.test.ts +110 -0
- package/src/lock/capability.ts +89 -0
- package/src/lock/index.ts +15 -0
- package/src/lock/node_modules/.vitest/results.json +1 -0
- package/src/lock/semaphore.ts +21 -0
- package/src/lock/shared-mutex.test.ts +537 -0
- package/src/lock/shared-mutex.ts +242 -0
- package/src/lock/utils.test.ts +165 -0
- package/src/lock/utils.ts +135 -0
- package/src/lodash-es/index.ts +1 -0
- package/src/math/degree.ts +16 -0
- package/src/math/index.ts +7 -0
- package/src/math/math.test.ts +40 -0
- package/src/math/math.ts +64 -0
- package/src/math/node_modules/.vitest/results.json +1 -0
- package/src/math/vector.test.ts +73 -0
- package/src/math/vector.ts +114 -0
- package/src/network/client.interface.ts +104 -0
- package/src/network/client.web.ts +24 -0
- package/src/network/index.common.ts +10 -0
- package/src/network/index.ts +2 -0
- package/src/network/plugins/retry.ts +98 -0
- package/src/objects/deep-clone.test.ts +40 -0
- package/src/objects/deep-clone.ts +13 -0
- package/src/objects/deep-equal.test.ts +86 -0
- package/src/objects/deep-equal.ts +60 -0
- package/src/objects/index.ts +4 -0
- package/src/platform/index.ts +64 -0
- package/src/promise/index.ts +16 -0
- package/src/promise/promise.test.ts +254 -0
- package/src/promise/promise.ts +212 -0
- package/src/scheduler/callback-token.ts +31 -0
- package/src/scheduler/core/actuator-args.test.ts +47 -0
- package/src/scheduler/core/actuator.test.ts +82 -0
- package/src/scheduler/core/actuator.ts +58 -0
- package/src/scheduler/core/chunk-scheduler.test.ts +54 -0
- package/src/scheduler/core/chunk-scheduler.ts +28 -0
- package/src/scheduler/core/node_modules/.vitest/results.json +1 -0
- package/src/scheduler/core/scheduler.test.ts +328 -0
- package/src/scheduler/core/scheduler.ts +172 -0
- package/src/scheduler/core/task-queue.test.ts +78 -0
- package/src/scheduler/core/task-queue.ts +44 -0
- package/src/scheduler/core/task.test.ts +34 -0
- package/src/scheduler/core/task.ts +52 -0
- package/src/scheduler/core/utils.ts +48 -0
- package/src/scheduler/executor/abstract-executor.test.ts +44 -0
- package/src/scheduler/executor/abstract-executor.ts +38 -0
- package/src/scheduler/executor/executor.interface.ts +39 -0
- package/src/scheduler/executor/idle-callback-executor.test.ts +70 -0
- package/src/scheduler/executor/idle-callback-executor.ts +98 -0
- package/src/scheduler/executor/make-executor.ts +18 -0
- package/src/scheduler/executor/post-message-executor.test.ts +66 -0
- package/src/scheduler/executor/post-message-executor.ts +52 -0
- package/src/scheduler/index.ts +15 -0
- package/src/scheduler/lv-scheduler-callback.ts +19 -0
- package/src/scheduler/lv-scheduler-config.ts +17 -0
- package/src/scheduler/type.ts +48 -0
- package/src/sprintf/index.ts +2 -0
- package/src/sprintf/sprintf.test.ts +95 -0
- package/src/sprintf/sprintf.ts +97 -0
- package/src/structure/graph.test.ts +181 -0
- package/src/structure/graph.ts +105 -0
- package/src/structure/index.ts +8 -0
- package/src/structure/linked-list.test.ts +74 -0
- package/src/structure/linked-list.ts +145 -0
- package/src/structure/min-heap.test.ts +71 -0
- package/src/structure/min-heap.ts +91 -0
- package/src/type/REAME.md +2 -0
- package/src/type/distributive-omit.interface.ts +4 -0
- package/src/type/index.ts +3 -0
- package/src/type/object-key-paths.interface.ts +40 -0
- package/src/undo-redo-stack/README.md +61 -0
- package/src/undo-redo-stack/action-stack.test.ts +330 -0
- package/src/undo-redo-stack/action-stack.ts +150 -0
- package/src/undo-redo-stack/element.ts +4 -0
- package/src/undo-redo-stack/index.ts +7 -0
- package/src/undo-redo-stack/state-stack.test.ts +118 -0
- package/src/undo-redo-stack/state-stack.ts +133 -0
- package/src/uuid/index.ts +7 -0
- package/src/uuid/uuid.ts +86 -0
- package/src/worker/cors-worker.ts +38 -0
- package/src/worker/index.ts +4 -0
- package/src/worker/node_modules/.vitest/results.json +1 -0
- package/src/worker/promise-worker-main-thread.test.ts +91 -0
- package/src/worker/promise-worker-main-thread.ts +76 -0
- package/src/worker/promise-worker-worker-thread.ts +64 -0
- package/src/worker/promise-worker.interface.ts +15 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type Mock } from 'vitest';
|
|
2
|
+
import { defer, type Deferred } from '@/promise';
|
|
3
|
+
import { AsyncQueue } from './queue';
|
|
4
|
+
|
|
5
|
+
const nextTick = () => {
|
|
6
|
+
return new Promise<void>((res) => {
|
|
7
|
+
setTimeout(() => {
|
|
8
|
+
res();
|
|
9
|
+
}, 0);
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const getTask = (): [() => Promise<void>, Deferred<void>, () => Mock<any, any>] => {
|
|
14
|
+
const defer1 = defer();
|
|
15
|
+
const mockFn1 = vi.fn();
|
|
16
|
+
|
|
17
|
+
return [
|
|
18
|
+
async () => {
|
|
19
|
+
mockFn1();
|
|
20
|
+
await defer1.promise;
|
|
21
|
+
},
|
|
22
|
+
defer1,
|
|
23
|
+
mockFn1,
|
|
24
|
+
];
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
describe('AsyncQueue', () => {
|
|
28
|
+
test('base', async () => {
|
|
29
|
+
const queue = new AsyncQueue({
|
|
30
|
+
concurrent: 1,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const [fn1, defer1, mockFn1] = getTask();
|
|
34
|
+
queue.addTask(fn1);
|
|
35
|
+
|
|
36
|
+
const [fn2, defer2, mockFn2] = getTask();
|
|
37
|
+
queue.addTask(fn2);
|
|
38
|
+
|
|
39
|
+
expect(mockFn1).toBeCalled();
|
|
40
|
+
expect(mockFn2).not.toBeCalled();
|
|
41
|
+
|
|
42
|
+
defer1.resolve();
|
|
43
|
+
await nextTick();
|
|
44
|
+
|
|
45
|
+
expect(mockFn2).toBeCalled();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('base 2', async () => {
|
|
49
|
+
const queue = new AsyncQueue({
|
|
50
|
+
concurrent: 2,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const [fn1, defer1, mockFn1] = getTask();
|
|
54
|
+
queue.addTask(fn1);
|
|
55
|
+
|
|
56
|
+
const [fn2, defer2, mockFn2] = getTask();
|
|
57
|
+
queue.addTask(fn2);
|
|
58
|
+
|
|
59
|
+
const [fn3, defer3, mockFn3] = getTask();
|
|
60
|
+
queue.addTask(fn3);
|
|
61
|
+
|
|
62
|
+
expect(mockFn1).toBeCalled();
|
|
63
|
+
expect(mockFn2).toBeCalled();
|
|
64
|
+
expect(mockFn3).not.toBeCalled();
|
|
65
|
+
|
|
66
|
+
defer1.resolve();
|
|
67
|
+
await nextTick();
|
|
68
|
+
expect(mockFn3).toBeCalled();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 异步任务队列
|
|
3
|
+
*/
|
|
4
|
+
import { Disposable } from '@/dispose';
|
|
5
|
+
import { AsyncTask, type IAsyncTask } from './task';
|
|
6
|
+
import type { ICancellationToken } from '../cancellation';
|
|
7
|
+
|
|
8
|
+
type IAsyncQueue = {
|
|
9
|
+
/** 队列的任务并发数 */
|
|
10
|
+
concurrent: number;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export class AsyncQueue extends Disposable {
|
|
14
|
+
private readonly _queue: AsyncTask[] = [];
|
|
15
|
+
private readonly _maxConcurrent: number = 1;
|
|
16
|
+
private _execCounter: number = 0;
|
|
17
|
+
|
|
18
|
+
constructor(options: IAsyncQueue) {
|
|
19
|
+
super();
|
|
20
|
+
// 初始化最大并发数
|
|
21
|
+
this._maxConcurrent = options.concurrent;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** 添加一个异步任务到队列 */
|
|
25
|
+
addTask(
|
|
26
|
+
callback: (cancellation: ICancellationToken) => Promise<void>,
|
|
27
|
+
cancellationToken?: ICancellationToken,
|
|
28
|
+
): IAsyncTask {
|
|
29
|
+
if (cancellationToken?.isCancellationRequested) {
|
|
30
|
+
return new AsyncTask(null);
|
|
31
|
+
}
|
|
32
|
+
const task = new AsyncTask(callback);
|
|
33
|
+
// 将任务函数加入队列
|
|
34
|
+
this._queue.push(this._store.add(task));
|
|
35
|
+
// 尝试执行下一个任务
|
|
36
|
+
this._next();
|
|
37
|
+
|
|
38
|
+
return task;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 执行下一个任务,如果当前并发数小于最大并发数,并且队列不为空,则从队列中取出一个任务并执行,否则什么都不做
|
|
42
|
+
private _next() {
|
|
43
|
+
if (this._queue.length && this._execCounter < this._maxConcurrent && this._queue.length > 0) {
|
|
44
|
+
// 取出队列中的第一个任务函数,并从队列中移除它
|
|
45
|
+
const task = this._queue.shift()!;
|
|
46
|
+
// 增加当前并发数
|
|
47
|
+
this._execCounter++;
|
|
48
|
+
// 执行任务函数,并处理其返回的promise对象
|
|
49
|
+
task.safeExec().finally(() => {
|
|
50
|
+
// 不管成功还是失败,都要减少当前并发数,并执行下一个任务(递归调用)
|
|
51
|
+
this._execCounter--;
|
|
52
|
+
this._next();
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/* eslint-disable prefer-promise-reject-errors */
|
|
2
|
+
/* eslint-disable max-lines-per-function */
|
|
3
|
+
import { CancellationTokenSource } from '../cancellation';
|
|
4
|
+
import { AsyncTask } from './task';
|
|
5
|
+
|
|
6
|
+
describe('AsyncTask', () => {
|
|
7
|
+
test('resolve', async () => {
|
|
8
|
+
const callback = vi.fn();
|
|
9
|
+
const successCb = vi.fn();
|
|
10
|
+
const failureCb = vi.fn();
|
|
11
|
+
const cancelCb = vi.fn();
|
|
12
|
+
const task1 = new AsyncTask(() => {
|
|
13
|
+
callback();
|
|
14
|
+
return Promise.resolve();
|
|
15
|
+
});
|
|
16
|
+
task1.onSuccess(successCb);
|
|
17
|
+
task1.onFailure(failureCb);
|
|
18
|
+
task1.onCancel(cancelCb);
|
|
19
|
+
|
|
20
|
+
const result1 = await task1.safeExec();
|
|
21
|
+
expect(callback).toHaveBeenCalled();
|
|
22
|
+
expect(successCb).toHaveBeenCalled();
|
|
23
|
+
expect(failureCb).not.toHaveBeenCalled();
|
|
24
|
+
expect(cancelCb).not.toHaveBeenCalled();
|
|
25
|
+
expect(result1).toBe(undefined);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('reject', async () => {
|
|
29
|
+
const callback = vi.fn();
|
|
30
|
+
const successCb = vi.fn();
|
|
31
|
+
const failureCb = vi.fn();
|
|
32
|
+
const cancelCb = vi.fn();
|
|
33
|
+
const error = new Error('error');
|
|
34
|
+
const rej = Promise.reject(error);
|
|
35
|
+
const task1 = new AsyncTask(() => {
|
|
36
|
+
callback();
|
|
37
|
+
return rej;
|
|
38
|
+
});
|
|
39
|
+
task1.onSuccess(successCb);
|
|
40
|
+
task1.onFailure(failureCb);
|
|
41
|
+
task1.onCancel(cancelCb);
|
|
42
|
+
|
|
43
|
+
const result1 = await task1.safeExec();
|
|
44
|
+
expect(callback).toHaveBeenCalled();
|
|
45
|
+
expect(successCb).not.toHaveBeenCalled();
|
|
46
|
+
expect(failureCb).toHaveBeenCalled();
|
|
47
|
+
expect(cancelCb).not.toHaveBeenCalled();
|
|
48
|
+
expect(result1).toBe(undefined);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('cancel', async () => {
|
|
52
|
+
const callback = vi.fn();
|
|
53
|
+
const successCb = vi.fn();
|
|
54
|
+
const failureCb = vi.fn();
|
|
55
|
+
const cancelCb = vi.fn();
|
|
56
|
+
|
|
57
|
+
const task1 = new AsyncTask(() => {
|
|
58
|
+
callback();
|
|
59
|
+
return Promise.reject();
|
|
60
|
+
});
|
|
61
|
+
task1.onSuccess(successCb);
|
|
62
|
+
task1.onFailure(failureCb);
|
|
63
|
+
task1.onCancel(cancelCb);
|
|
64
|
+
|
|
65
|
+
task1.cancel();
|
|
66
|
+
await task1.safeExec();
|
|
67
|
+
expect(callback).not.toHaveBeenCalled();
|
|
68
|
+
expect(successCb).not.toHaveBeenCalled();
|
|
69
|
+
expect(failureCb).not.toHaveBeenCalled();
|
|
70
|
+
expect(cancelCb).toHaveBeenCalled();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('cancel 2', async () => {
|
|
74
|
+
const callback = vi.fn();
|
|
75
|
+
const successCb = vi.fn();
|
|
76
|
+
const failureCb = vi.fn();
|
|
77
|
+
const cancelCb = vi.fn();
|
|
78
|
+
|
|
79
|
+
const task1 = new AsyncTask(() => {
|
|
80
|
+
callback();
|
|
81
|
+
return Promise.reject();
|
|
82
|
+
});
|
|
83
|
+
task1.onSuccess(successCb);
|
|
84
|
+
task1.onFailure(failureCb);
|
|
85
|
+
task1.onCancel(cancelCb);
|
|
86
|
+
|
|
87
|
+
await task1.safeExec();
|
|
88
|
+
task1.cancel();
|
|
89
|
+
expect(callback).toHaveBeenCalled();
|
|
90
|
+
expect(successCb).not.toHaveBeenCalled();
|
|
91
|
+
expect(failureCb).toHaveBeenCalled();
|
|
92
|
+
expect(cancelCb).not.toHaveBeenCalled();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Testing the behaviors of aborting with abort signal
|
|
97
|
+
* */
|
|
98
|
+
test('aborts a task before it is exected should prevent task from being executed', async () => {
|
|
99
|
+
const callback = vi.fn();
|
|
100
|
+
const successCb = vi.fn();
|
|
101
|
+
const failureCb = vi.fn();
|
|
102
|
+
const cancelCb = vi.fn();
|
|
103
|
+
|
|
104
|
+
const cancellationSource = new CancellationTokenSource();
|
|
105
|
+
|
|
106
|
+
const task1 = new AsyncTask(() => {
|
|
107
|
+
callback();
|
|
108
|
+
return Promise.reject();
|
|
109
|
+
}, cancellationSource.token);
|
|
110
|
+
|
|
111
|
+
task1.onSuccess(successCb);
|
|
112
|
+
task1.onFailure(failureCb);
|
|
113
|
+
task1.onCancel(cancelCb);
|
|
114
|
+
|
|
115
|
+
// aborts the task before it is executed
|
|
116
|
+
cancellationSource.cancel();
|
|
117
|
+
// The abort event of abort controller will be dispatched synchronously
|
|
118
|
+
|
|
119
|
+
await task1.safeExec();
|
|
120
|
+
|
|
121
|
+
expect(callback).not.toHaveBeenCalled();
|
|
122
|
+
expect(successCb).not.toHaveBeenCalled();
|
|
123
|
+
expect(failureCb).not.toHaveBeenCalled();
|
|
124
|
+
|
|
125
|
+
expect(cancelCb).toHaveBeenCalled();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('aborts a task after it has been executed should not cause the task to enter the cancelled stage', async () => {
|
|
129
|
+
const callback = vi.fn();
|
|
130
|
+
const successCb = vi.fn();
|
|
131
|
+
const failureCb = vi.fn();
|
|
132
|
+
const cancelCb = vi.fn();
|
|
133
|
+
|
|
134
|
+
const cancellationSource = new CancellationTokenSource();
|
|
135
|
+
|
|
136
|
+
const task1 = new AsyncTask(() => {
|
|
137
|
+
callback();
|
|
138
|
+
return Promise.reject();
|
|
139
|
+
}, cancellationSource.token);
|
|
140
|
+
task1.onSuccess(successCb);
|
|
141
|
+
task1.onFailure(failureCb);
|
|
142
|
+
task1.onCancel(cancelCb);
|
|
143
|
+
|
|
144
|
+
await task1.safeExec();
|
|
145
|
+
|
|
146
|
+
// aborts the task after it has been executed
|
|
147
|
+
cancellationSource.cancel();
|
|
148
|
+
|
|
149
|
+
expect(callback).toHaveBeenCalled();
|
|
150
|
+
expect(successCb).not.toHaveBeenCalled();
|
|
151
|
+
expect(failureCb).toHaveBeenCalled();
|
|
152
|
+
|
|
153
|
+
expect(cancelCb).not.toHaveBeenCalled();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Disposable, type IDisposable } from '@/dispose';
|
|
2
|
+
import { type Event, Emitter } from '@/event';
|
|
3
|
+
import { makeErrorBy, type ILvErrorRef } from '@/error';
|
|
4
|
+
import { CancellationToken, type ICancellationToken } from '../cancellation';
|
|
5
|
+
|
|
6
|
+
export interface IAsyncTask extends IDisposable {
|
|
7
|
+
onSuccess: Event<[]>;
|
|
8
|
+
onFailure: Event<[ILvErrorRef]>;
|
|
9
|
+
onCancel: Event<[]>;
|
|
10
|
+
|
|
11
|
+
/** 取消当前任务 */
|
|
12
|
+
cancel: () => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class AsyncTask extends Disposable implements IAsyncTask {
|
|
16
|
+
private readonly _onSuccess = this._store.add(new Emitter<[]>());
|
|
17
|
+
public readonly onSuccess = this._onSuccess.event;
|
|
18
|
+
|
|
19
|
+
private readonly _onFailure = this._store.add(new Emitter<[ILvErrorRef]>());
|
|
20
|
+
public readonly onFailure = this._onFailure.event;
|
|
21
|
+
|
|
22
|
+
private readonly _onCancel = this._store.add(new Emitter<[]>());
|
|
23
|
+
public readonly onCancel = this._onCancel.event;
|
|
24
|
+
|
|
25
|
+
private _isExec: boolean = false;
|
|
26
|
+
private _isCancel: boolean = false;
|
|
27
|
+
|
|
28
|
+
constructor(
|
|
29
|
+
private _callback: ((cancellation: ICancellationToken) => Promise<void>) | null,
|
|
30
|
+
private readonly _cancellationToken?: ICancellationToken,
|
|
31
|
+
) {
|
|
32
|
+
super();
|
|
33
|
+
|
|
34
|
+
this._cancellationToken?.onCancellationRequested(() => {
|
|
35
|
+
this.cancel();
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** 这个方法不对外暴露,只提供给 queue 使用. */
|
|
40
|
+
async safeExec(): Promise<void> {
|
|
41
|
+
if (this._isCancel || this._isExec) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
this._isExec = true;
|
|
47
|
+
await this._callback!(this._cancellationToken ?? CancellationToken.None);
|
|
48
|
+
this._onSuccess.fire();
|
|
49
|
+
} catch (err) {
|
|
50
|
+
/** handler error */
|
|
51
|
+
this._onFailure.fire(makeErrorBy(-1, 'exec error', err as Error));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
cancel(): void {
|
|
56
|
+
if (this._isCancel) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (this._isExec) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
this._isCancel = true;
|
|
64
|
+
this._callback = null;
|
|
65
|
+
this._onCancel.fire();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { invokeNextLoop } from './utils';
|
|
2
|
+
|
|
3
|
+
describe('invokeNextLoop', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
vi.useFakeTimers();
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it('invoke', () => {
|
|
9
|
+
let a = 0;
|
|
10
|
+
invokeNextLoop(() => {
|
|
11
|
+
a++;
|
|
12
|
+
});
|
|
13
|
+
expect(a).toBe(0);
|
|
14
|
+
vi.advanceTimersByTime(1);
|
|
15
|
+
expect(a).toBe(1);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('dispose', () => {
|
|
19
|
+
let a = 0;
|
|
20
|
+
const disposable = invokeNextLoop(() => {
|
|
21
|
+
a++;
|
|
22
|
+
});
|
|
23
|
+
expect(a).toBe(0);
|
|
24
|
+
disposable.dispose();
|
|
25
|
+
vi.advanceTimersByTime(1);
|
|
26
|
+
expect(a).toBe(0);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { getDefaultFormat, byteSizeFormat } from './format';
|
|
2
|
+
|
|
3
|
+
describe('getDefaultFormat', () => {
|
|
4
|
+
it('should return b for values less than 0.1KB', () => {
|
|
5
|
+
expect(getDefaultFormat(100)).toBe('b');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it('should return kb for values between 0.1KB and 0.1MB', () => {
|
|
9
|
+
expect(getDefaultFormat(1024)).toBe('kb');
|
|
10
|
+
expect(getDefaultFormat(10 * 1024)).toBe('kb');
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should return mb for values between 0.1MB and 1GB', () => {
|
|
14
|
+
expect(getDefaultFormat(1024 * 1024)).toBe('mb');
|
|
15
|
+
expect(getDefaultFormat(100 * 1024 * 1024)).toBe('mb');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should return gb for values between 1GB and 1TB', () => {
|
|
19
|
+
expect(getDefaultFormat(2 * 1024 * 1024 * 1024)).toBe('gb');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should return tb for values greater than 1TB', () => {
|
|
23
|
+
expect(getDefaultFormat(2 * 1024 * 1024 * 1024 * 1024)).toBe('tb');
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('byteSizeFormat', () => {
|
|
28
|
+
it('should format bytes correctly', () => {
|
|
29
|
+
expect(byteSizeFormat(100, 'b')).toBe('100B');
|
|
30
|
+
expect(byteSizeFormat(100.123, 'b')).toBe('100.12B');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should format kilobytes correctly', () => {
|
|
34
|
+
expect(byteSizeFormat(1024, 'kb')).toBe('1KB');
|
|
35
|
+
expect(byteSizeFormat(1536, 'kb')).toBe('1.50KB');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should format megabytes correctly', () => {
|
|
39
|
+
expect(byteSizeFormat(1024 * 1024, 'mb')).toBe('1MB');
|
|
40
|
+
expect(byteSizeFormat(1.5 * 1024 * 1024, 'mb')).toBe('1.50MB');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should format gigabytes correctly', () => {
|
|
44
|
+
expect(byteSizeFormat(1024 * 1024 * 1024, 'gb')).toBe('1GB');
|
|
45
|
+
expect(byteSizeFormat(2.5 * 1024 * 1024 * 1024, 'gb')).toBe('2.50GB');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should format terabytes correctly', () => {
|
|
49
|
+
expect(byteSizeFormat(1024 * 1024 * 1024 * 1024, 'tb')).toBe('1TB');
|
|
50
|
+
expect(byteSizeFormat(1.5 * 1024 * 1024 * 1024 * 1024, 'tb')).toBe('1.50TB');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should use default format when no format is specified', () => {
|
|
54
|
+
expect(byteSizeFormat(100)).toBe('100B');
|
|
55
|
+
expect(byteSizeFormat(1024 * 100)).toBe('100KB');
|
|
56
|
+
expect(byteSizeFormat(1024 * 1024 * 100)).toBe('100MB');
|
|
57
|
+
expect(byteSizeFormat(1024 * 1024 * 1024 * 2)).toBe('2GB');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should remove .00 from formatted values', () => {
|
|
61
|
+
expect(byteSizeFormat(1024 * 1024, 'mb')).toBe('1MB');
|
|
62
|
+
expect(byteSizeFormat(2000, 'b')).toBe('2000B');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function getDefaultFormat(value: number) {
|
|
2
|
+
if (value < 0.1 * 1024) {
|
|
3
|
+
// 小于0.1KB,则转化成B
|
|
4
|
+
return 'b';
|
|
5
|
+
}
|
|
6
|
+
if (value < 0.1 * 1024 * 1024) {
|
|
7
|
+
// 小于0.1MB,则转化成KB
|
|
8
|
+
return 'kb';
|
|
9
|
+
}
|
|
10
|
+
if (value < 1 * 1024 * 1024 * 1024) {
|
|
11
|
+
// 小于0.1GB,则转化成MB
|
|
12
|
+
return 'mb';
|
|
13
|
+
}
|
|
14
|
+
if (value < 1 * 1024 * 1024 * 1024 * 1024) {
|
|
15
|
+
// 其他转化成GB
|
|
16
|
+
return 'gb';
|
|
17
|
+
}
|
|
18
|
+
return 'tb';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const formatMap = {
|
|
22
|
+
b: (value: number) => `${value.toFixed(2)}B`,
|
|
23
|
+
kb: (value: number) => `${(value / 1024).toFixed(2)}KB`,
|
|
24
|
+
mb: (value: number) => `${(value / (1024 * 1024)).toFixed(2)}MB`,
|
|
25
|
+
gb: (value: number) => `${(value / (1024 * 1024 * 1024)).toFixed(2)}GB`,
|
|
26
|
+
tb: (value: number) => `${(value / (1024 * 1024 * 1024 * 1024)).toFixed(2)}TB`,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export function byteSizeFormat(limit: number, format?: 'b' | 'kb' | 'mb' | 'gb' | 'tb'): string {
|
|
30
|
+
let size = '';
|
|
31
|
+
|
|
32
|
+
const resetFormat = format || getDefaultFormat(limit);
|
|
33
|
+
|
|
34
|
+
size = formatMap[resetFormat](limit);
|
|
35
|
+
|
|
36
|
+
const sizeStr = `${size}`; // 转成字符串
|
|
37
|
+
const index = sizeStr.indexOf('.'); // 获取小数点处的索引
|
|
38
|
+
const dou = sizeStr.substr(index + 1, 2); // 获取小数点后两位的值
|
|
39
|
+
if (dou === '00') {
|
|
40
|
+
// 判断后两位是否为00,如果是则删除00
|
|
41
|
+
return sizeStr.substring(0, index) + sizeStr.substr(index + 3, 2);
|
|
42
|
+
}
|
|
43
|
+
return size;
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":"1.0.1","results":[[":format.test.ts",{"duration":2,"failed":false}]]}
|
package/src/byte/var.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { LRUCacheWithTimeout } from './lru-with-timeout';
|
|
2
|
+
|
|
3
|
+
class Foo {
|
|
4
|
+
constructor(public readonly value: string) {}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// LRU基本能力依然保留
|
|
8
|
+
describe('LRU Base', () => {
|
|
9
|
+
let cache: LRUCacheWithTimeout<Foo>;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
// 创建一个容量为5的缓存实例
|
|
13
|
+
cache = new LRUCacheWithTimeout<Foo>(5, 100);
|
|
14
|
+
|
|
15
|
+
// 向缓存中添加一些初始数据供测试使用
|
|
16
|
+
cache.put('1', new Foo('apple'));
|
|
17
|
+
cache.put('2', new Foo('banana'));
|
|
18
|
+
cache.put('3', new Foo('orange'));
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should return the value when getting an existing key', () => {
|
|
22
|
+
const result = cache.get('2');
|
|
23
|
+
expect(result).not.toBeUndefined();
|
|
24
|
+
expect(result!.value).toBe('banana');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should return undefined when getting a non-existing key', () => {
|
|
28
|
+
const result = cache.get('4');
|
|
29
|
+
expect(result).toBeUndefined();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should update the value when putting an existing key', () => {
|
|
33
|
+
cache.put('2', new Foo('grapefruit'));
|
|
34
|
+
const result = cache.get('2');
|
|
35
|
+
expect(result).not.toBeUndefined();
|
|
36
|
+
expect(result!.value).toBe('grapefruit');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should add the key-value pair to the cache when putting a new key', () => {
|
|
40
|
+
cache.put('4', new Foo('kiwi'));
|
|
41
|
+
const result = cache.get('4');
|
|
42
|
+
expect(result).not.toBeUndefined();
|
|
43
|
+
expect(result!.value).toBe('kiwi');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should remove the least recently used item when the cache is full and a new item is added', () => {
|
|
47
|
+
cache.put('4', new Foo('kiwi'));
|
|
48
|
+
cache.put('5', new Foo('pear'));
|
|
49
|
+
cache.put('6', new Foo('mango'));
|
|
50
|
+
// 检查最早添加的项是否被移除
|
|
51
|
+
const result1 = cache.get('1');
|
|
52
|
+
const result2 = cache.get('2');
|
|
53
|
+
expect(result1).toBeUndefined();
|
|
54
|
+
expect(result2).not.toBeUndefined();
|
|
55
|
+
expect(result2!.value).toBe('banana');
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// 判断超时逻辑
|
|
60
|
+
describe('Timeout', () => {
|
|
61
|
+
beforeAll(() => {
|
|
62
|
+
vi.useFakeTimers();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('timeout', () => {
|
|
66
|
+
const now = Date.now();
|
|
67
|
+
const cache = new LRUCacheWithTimeout<Foo>(5, 200);
|
|
68
|
+
cache.put('1', new Foo('capcut'));
|
|
69
|
+
const result1 = cache.get('1');
|
|
70
|
+
expect(result1).not.toBeUndefined();
|
|
71
|
+
|
|
72
|
+
vi.spyOn(Date, 'now').mockImplementationOnce(() => {
|
|
73
|
+
return now + 100;
|
|
74
|
+
});
|
|
75
|
+
vi.advanceTimersByTime(100);
|
|
76
|
+
|
|
77
|
+
const result2 = cache.get('1');
|
|
78
|
+
expect(result2).not.toBeUndefined();
|
|
79
|
+
|
|
80
|
+
vi.spyOn(Date, 'now').mockImplementationOnce(() => {
|
|
81
|
+
return now + 300;
|
|
82
|
+
});
|
|
83
|
+
vi.advanceTimersByTime(300);
|
|
84
|
+
|
|
85
|
+
const result3 = cache.get('1');
|
|
86
|
+
expect(result3).toBeUndefined();
|
|
87
|
+
});
|
|
88
|
+
});
|