From 263450ea97744ffa3435a10d177203e47e4b9e96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BE=AF=E5=AD=A6=E5=8F=8B?= Date: Mon, 9 May 2022 16:03:18 +0800 Subject: [PATCH 1/7] add next-tick init code --- .gitignore | 3 +++ package-lock.json | 14 ++++++++++++++ package.json | 24 ++++++++++++++++++++++++ src/batching.ts | 35 +++++++++++++++++++++++++++++++++++ src/flush.ts | 27 +++++++++++++++++++++++++++ src/mian.ts | 10 ++++++++++ src/nextLoop.ts | 15 +++++++++++++++ src/queue.ts | 14 ++++++++++++++ src/scheduler.ts | 10 ++++++++++ src/typedef.ts | 6 ++++++ tsconfig.json | 16 ++++++++++++++++ typedef.d.ts | 7 +++++++ 12 files changed, 181 insertions(+) create mode 100644 .gitignore create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/batching.ts create mode 100644 src/flush.ts create mode 100644 src/mian.ts create mode 100644 src/nextLoop.ts create mode 100644 src/queue.ts create mode 100644 src/scheduler.ts create mode 100644 src/typedef.ts create mode 100644 tsconfig.json create mode 100644 typedef.d.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9eae3d9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ + +node_modules/ +out/ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..cd73c77 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,14 @@ +{ + "name": "next-tick", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "typescript": { + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", + "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..29a6195 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "next-tick", + "version": "0.0.0", + "description": "", + "types": "./typedef.d.ts", + "main": "out/main.js", + "scripts": { + "tsc":"tsc" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/lsxqXs/next-tick.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/lsxqXs/next-tick/issues" + }, + "homepage": "https://github.com/lsxqXs/next-tick#readme", + "devDependencies": { + "typescript": "^4.6.4" + } +} diff --git a/src/batching.ts b/src/batching.ts new file mode 100644 index 0000000..23e3608 --- /dev/null +++ b/src/batching.ts @@ -0,0 +1,35 @@ + +import {ExecutionCallback} from "./typedef"; + +let BatchingExecution = false; + +/** + * resume 重新开始 + */ +export function resumeExecutionCallback() { + BatchingExecution = false; +} + +/** + * pause 暂停执行 + */ +export function pauseExecutionCallback() { + BatchingExecution = true; +} + +/** + * true -> 执行中 + * @returns bool + */ +export function hasInExecution() { + return BatchingExecution; +} + + +export function runWithBatchingExecution(callback: ExecutionCallback) { + try { + return (!(hasInExecution())) && callback(); + } finally { + pauseExecutionCallback(); + } +} \ No newline at end of file diff --git a/src/flush.ts b/src/flush.ts new file mode 100644 index 0000000..6d38b46 --- /dev/null +++ b/src/flush.ts @@ -0,0 +1,27 @@ +import { pauseExecutionCallback } from "./batching"; +import { requestNextLoopExecutionCallback } from "./nextLoop"; +import { callbackQueue } from "./queue"; + +export function flushNextPendingExecutionCallbackQueue() { + + let currentCallbackQueue = callbackQueue.nextCallbackQueue; + callbackQueue.nextCallbackQueue = callbackQueue.processCallbackQueue; + + while (currentCallbackQueue.length > 0) { + let callback = currentCallbackQueue.shift(); + callback(); + } + + // 交替执行 + callbackQueue.processCallbackQueue = currentCallbackQueue; + + // 队列不为空, 我希望在下一轮循环中执行他们 + if (callbackQueue.nextCallbackQueue.length > 0) { + requestNextLoopExecutionCallback(); + } + else { + // 本轮循环中立即关闭,否增,下一轮循环关闭时会存在未被执行的回调函数 + pauseExecutionCallback(); + } + +} \ No newline at end of file diff --git a/src/mian.ts b/src/mian.ts new file mode 100644 index 0000000..acc732a --- /dev/null +++ b/src/mian.ts @@ -0,0 +1,10 @@ + +import {ExecutionCallback} from "./typedef"; +import { schedulerOnCallbackExecution } from "./scheduler"; + + +export function nextTick(fn:ExecutionCallback) { + schedulerOnCallbackExecution(fn); +} + +export default nextTick; diff --git a/src/nextLoop.ts b/src/nextLoop.ts new file mode 100644 index 0000000..0c21a74 --- /dev/null +++ b/src/nextLoop.ts @@ -0,0 +1,15 @@ +import { flushNextPendingExecutionCallbackQueue } from "./flush"; +import { pauseExecutionCallback } from "./batching"; + +const channel = new MessageChannel(); + +channel.port1.onmessage = flushNextPendingExecutionCallbackQueue; +channel.port2.onmessage = pauseExecutionCallback; + +export function requestNextLoopExecutionCallback() { + channel.port2.postMessage(null); +} + +export function nextLoopPauseExecution() { + channel.port1.postMessage(null); +} diff --git a/src/queue.ts b/src/queue.ts new file mode 100644 index 0000000..8eda515 --- /dev/null +++ b/src/queue.ts @@ -0,0 +1,14 @@ + +import {ExecutionCallback} from "./typedef"; + + + +interface Queue { + nextCallbackQueue: ExecutionCallback[]; + processCallbackQueue: ExecutionCallback[]; +} + +export const callbackQueue: Queue = { + nextCallbackQueue: [], + processCallbackQueue: [] +}; diff --git a/src/scheduler.ts b/src/scheduler.ts new file mode 100644 index 0000000..6edcff3 --- /dev/null +++ b/src/scheduler.ts @@ -0,0 +1,10 @@ +import { runWithBatchingExecution } from "./batching"; +import { requestNextLoopExecutionCallback } from "./nextLoop"; +import { callbackQueue } from "./queue"; +import {ExecutionCallback} from "./typedef"; + + +export function schedulerOnCallbackExecution(fn:ExecutionCallback) { + callbackQueue.nextCallbackQueue.push(fn); + runWithBatchingExecution(requestNextLoopExecutionCallback); +} diff --git a/src/typedef.ts b/src/typedef.ts new file mode 100644 index 0000000..316b598 --- /dev/null +++ b/src/typedef.ts @@ -0,0 +1,6 @@ + + + +export interface ExecutionCallback { + (): void; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e4f1fea --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "declaration": true, + "target": "ESNext", + "declarationDir": "./out/@types", + "outDir": "./out", + "typeRoots": [ + "typedef.d.ts" + ] + }, + "include": [ + "src/*.ts", + "typedef.d.ts" + ] +} \ No newline at end of file diff --git a/typedef.d.ts b/typedef.d.ts new file mode 100644 index 0000000..1ff2013 --- /dev/null +++ b/typedef.d.ts @@ -0,0 +1,7 @@ + + +// @ts-ignore +export * from "./out/@types"; + +declare module "next-tick" { +} \ No newline at end of file From 24928285ff3aa9a733ca958b1d613a510561a86f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BE=AF=E5=AD=A6=E5=8F=8B?= Date: Tue, 10 May 2022 08:53:54 +0800 Subject: [PATCH 2/7] flushing --- package.json | 23 +++++++++++++++++------ src/queue.ts | 3 +++ tsconfig.json | 8 ++------ typedef.d.ts | 3 +-- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 29a6195..6d5286c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "next-tick", "version": "0.0.0", - "description": "", + "description": "next event loop, execute callback function before setTimeout", "types": "./typedef.d.ts", "main": "out/main.js", "scripts": { @@ -9,16 +9,27 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/lsxqXs/next-tick.git" + "url": "https://github.com/lsxqXs/next-tick.git" }, - "keywords": [], - "author": "", + "keywords": [ + "promise", + "event loop", + "setTimeout", + "promise", + "async" + ], + "author": "lsxq", "license": "ISC", "bugs": { "url": "https://github.com/lsxqXs/next-tick/issues" }, - "homepage": "https://github.com/lsxqXs/next-tick#readme", + "homepage": "https://github.com/lsxqXs/next-tick#README", "devDependencies": { "typescript": "^4.6.4" - } + }, + "files": [ + "README.md", + "index.d.ts", + "out" + ] } diff --git a/src/queue.ts b/src/queue.ts index 8eda515..0a1405c 100644 --- a/src/queue.ts +++ b/src/queue.ts @@ -12,3 +12,6 @@ export const callbackQueue: Queue = { nextCallbackQueue: [], processCallbackQueue: [] }; + +// 使用链表来做 +// 支持ms diff --git a/tsconfig.json b/tsconfig.json index e4f1fea..c683d79 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,13 +4,9 @@ "declaration": true, "target": "ESNext", "declarationDir": "./out/@types", - "outDir": "./out", - "typeRoots": [ - "typedef.d.ts" - ] + "outDir": "./out" }, "include": [ - "src/*.ts", - "typedef.d.ts" + "src/*.ts" ] } \ No newline at end of file diff --git a/typedef.d.ts b/typedef.d.ts index 1ff2013..904474f 100644 --- a/typedef.d.ts +++ b/typedef.d.ts @@ -1,7 +1,6 @@ -// @ts-ignore -export * from "./out/@types"; +export * from "./out/@types/mian"; declare module "next-tick" { } \ No newline at end of file From 316f305e62ca8ac3485e6e7e450f9b635a7da85e Mon Sep 17 00:00:00 2001 From: lsxqer Date: Sun, 12 Jun 2022 10:34:22 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E5=88=86=E7=A6=BB=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E5=BE=AA=E7=8E=AF=E5=92=8C=E4=B8=8B=E4=B8=80=E6=AC=A1=E5=BE=AA?= =?UTF-8?q?=E7=8E=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/flush.ts | 9 +++++++-- src/nextLoop.ts | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/flush.ts b/src/flush.ts index 6d38b46..c6d58fd 100644 --- a/src/flush.ts +++ b/src/flush.ts @@ -2,7 +2,8 @@ import { pauseExecutionCallback } from "./batching"; import { requestNextLoopExecutionCallback } from "./nextLoop"; import { callbackQueue } from "./queue"; -export function flushNextPendingExecutionCallbackQueue() { + +export function flushCurrentCallback() { let currentCallbackQueue = callbackQueue.nextCallbackQueue; callbackQueue.nextCallbackQueue = callbackQueue.processCallbackQueue; @@ -12,9 +13,13 @@ export function flushNextPendingExecutionCallbackQueue() { callback(); } - // 交替执行 callbackQueue.processCallbackQueue = currentCallbackQueue; +} + +export function nextLoopFlushCallbackQueue() { + flushCurrentCallback(); + // 队列不为空, 我希望在下一轮循环中执行他们 if (callbackQueue.nextCallbackQueue.length > 0) { requestNextLoopExecutionCallback(); diff --git a/src/nextLoop.ts b/src/nextLoop.ts index 0c21a74..b8e2bf9 100644 --- a/src/nextLoop.ts +++ b/src/nextLoop.ts @@ -1,9 +1,9 @@ -import { flushNextPendingExecutionCallbackQueue } from "./flush"; +import { nextLoopFlushCallbackQueue } from "./flush"; import { pauseExecutionCallback } from "./batching"; const channel = new MessageChannel(); -channel.port1.onmessage = flushNextPendingExecutionCallbackQueue; +channel.port1.onmessage = nextLoopFlushCallbackQueue; channel.port2.onmessage = pauseExecutionCallback; export function requestNextLoopExecutionCallback() { From 0ea14bf39ca2b11e7f9e9d12fed857d09d640a13 Mon Sep 17 00:00:00 2001 From: HXY Date: Thu, 23 Nov 2023 12:09:18 +0800 Subject: [PATCH 4/7] =?UTF-8?q?npm=E5=8F=AF=E4=BB=8Egithub=E5=AE=89?= =?UTF-8?q?=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 ++++- package.json | 7 +++++-- src/batching.ts | 19 ++++++++++------- src/flush.ts | 54 ++++++++++++++++++++++++++++++++++++++++--------- src/queue.ts | 4 +--- src/slice.ts | 24 ++++++++++++++++++++++ 6 files changed, 91 insertions(+), 22 deletions(-) create mode 100644 src/slice.ts diff --git a/.gitignore b/.gitignore index 9eae3d9..9ead8e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ node_modules/ -out/ \ No newline at end of file +out/ +package-lock.json + +.DS_Store diff --git a/package.json b/package.json index 6d5286c..eb6f058 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,12 @@ { "name": "next-tick", - "version": "0.0.0", + "version": "0.0.1", "description": "next event loop, execute callback function before setTimeout", "types": "./typedef.d.ts", - "main": "out/main.js", + "main": "src/main.ts", + "module": "src/main.ts", + "browser": "src/main.ts", + "scripts": { "tsc":"tsc" }, diff --git a/src/batching.ts b/src/batching.ts index 23e3608..578e842 100644 --- a/src/batching.ts +++ b/src/batching.ts @@ -1,24 +1,24 @@ -import {ExecutionCallback} from "./typedef"; +import { ExecutionCallback } from "./typedef"; -let BatchingExecution = false; +let BatchingExecution = true; /** * resume 重新开始 */ export function resumeExecutionCallback() { - BatchingExecution = false; + BatchingExecution = true; } /** * pause 暂停执行 */ export function pauseExecutionCallback() { - BatchingExecution = true; + BatchingExecution = false; } /** - * true -> 执行中 + * false -> 执行中 * @returns bool */ export function hasInExecution() { @@ -26,10 +26,15 @@ export function hasInExecution() { } + export function runWithBatchingExecution(callback: ExecutionCallback) { try { - return (!(hasInExecution())) && callback(); + const next = hasInExecution(); + if (next) { + return callback(); + } } finally { pauseExecutionCallback(); } -} \ No newline at end of file +} + diff --git a/src/flush.ts b/src/flush.ts index c6d58fd..e27d816 100644 --- a/src/flush.ts +++ b/src/flush.ts @@ -1,32 +1,68 @@ -import { pauseExecutionCallback } from "./batching"; +import { resumeExecutionCallback } from "./batching"; import { requestNextLoopExecutionCallback } from "./nextLoop"; import { callbackQueue } from "./queue"; +import { markStartTime, shouldYieldWithStart } from "./slice"; +import { ExecutionCallback } from "./typedef"; +let currentCallbackQueue: ExecutionCallback[] | null = null; + + +function requestCurrentQueue() { + if (currentCallbackQueue !== null) { + return currentCallbackQueue; + } + if (callbackQueue.nextCallbackQueue.length > 0) { + currentCallbackQueue = callbackQueue.nextCallbackQueue; + callbackQueue.nextCallbackQueue = []; + return currentCallbackQueue; + } + + return null; +} + +function shouldNextLoop() { + if (currentCallbackQueue !== null) { + return true; + } + if (callbackQueue.nextCallbackQueue.length > 0) { + return true; + } + return false; +} + export function flushCurrentCallback() { + markStartTime(); + let queue = requestCurrentQueue(); + if (queue === null) { + return; + } - let currentCallbackQueue = callbackQueue.nextCallbackQueue; - callbackQueue.nextCallbackQueue = callbackQueue.processCallbackQueue; + let s = Date.now(); - while (currentCallbackQueue.length > 0) { - let callback = currentCallbackQueue.shift(); + while (queue.length > 0 && !shouldYieldWithStart()) { + let callback = queue.shift(); callback(); } - callbackQueue.processCallbackQueue = currentCallbackQueue; + let s2 = Date.now(); + console.log(s2 - s, currentCallbackQueue.length, "暂定执行执行终端", "nextLoopFlushCallbackQueue"); + if (queue.length === 0) { + currentCallbackQueue = null; + } } export function nextLoopFlushCallbackQueue() { flushCurrentCallback(); - + // 队列不为空, 我希望在下一轮循环中执行他们 - if (callbackQueue.nextCallbackQueue.length > 0) { + if (shouldNextLoop()) { requestNextLoopExecutionCallback(); } else { // 本轮循环中立即关闭,否增,下一轮循环关闭时会存在未被执行的回调函数 - pauseExecutionCallback(); + resumeExecutionCallback(); } } \ No newline at end of file diff --git a/src/queue.ts b/src/queue.ts index 0a1405c..cc86b35 100644 --- a/src/queue.ts +++ b/src/queue.ts @@ -5,12 +5,10 @@ import {ExecutionCallback} from "./typedef"; interface Queue { nextCallbackQueue: ExecutionCallback[]; - processCallbackQueue: ExecutionCallback[]; } export const callbackQueue: Queue = { - nextCallbackQueue: [], - processCallbackQueue: [] + nextCallbackQueue: [] }; // 使用链表来做 diff --git a/src/slice.ts b/src/slice.ts new file mode 100644 index 0000000..4f0db45 --- /dev/null +++ b/src/slice.ts @@ -0,0 +1,24 @@ + + +let _startTime: number | null = null; + + +export function markStartTime() { + _startTime = Date.now(); +} + + + +export function shouldYieldWithStart() { + let end = Date.now(); + let step = end - _startTime; + + + if (step > 80) { + _startTime = end; + return true; + } + + return false; +} + From 273cc9c9e70b299d6bf04fd1264b784a0256e983 Mon Sep 17 00:00:00 2001 From: HXY Date: Thu, 23 Nov 2023 12:35:48 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9ts=E5=A3=B0=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + src/{mian.ts => main.ts} | 0 typedef.d.ts | 4 +++- 3 files changed, 4 insertions(+), 1 deletion(-) rename src/{mian.ts => main.ts} (100%) diff --git a/.gitignore b/.gitignore index 9ead8e1..205089a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ out/ package-lock.json .DS_Store +bun.lockb \ No newline at end of file diff --git a/src/mian.ts b/src/main.ts similarity index 100% rename from src/mian.ts rename to src/main.ts diff --git a/typedef.d.ts b/typedef.d.ts index 904474f..be1fca8 100644 --- a/typedef.d.ts +++ b/typedef.d.ts @@ -1,6 +1,8 @@ -export * from "./out/@types/mian"; + declare module "next-tick" { + export function nextTick(callback: () => void): void; + export default nextTick; } \ No newline at end of file From 701a1459fb0f54582ecc4d407bf500d488788080 Mon Sep 17 00:00:00 2001 From: HXY Date: Thu, 23 Nov 2023 13:14:52 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E5=A3=B0=E6=98=8E=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=92=8Cjs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- out/@types/batching.d.ts | 15 +++++++++++ out/@types/flush.d.ts | 2 ++ out/@types/main.d.ts | 3 +++ out/@types/nextLoop.d.ts | 2 ++ out/@types/queue.d.ts | 6 +++++ out/@types/scheduler.d.ts | 2 ++ out/@types/slice.d.ts | 2 ++ out/@types/typedef.d.ts | 3 +++ out/batching.js | 31 +++++++++++++++++++++++ out/flush.js | 53 +++++++++++++++++++++++++++++++++++++++ out/main.js | 5 ++++ out/nextLoop.js | 11 ++++++++ out/queue.js | 5 ++++ out/scheduler.js | 7 ++++++ out/slice.js | 13 ++++++++++ out/typedef.js | 1 + package.json | 6 ++--- tsconfig.json | 1 + 19 files changed, 166 insertions(+), 4 deletions(-) create mode 100644 out/@types/batching.d.ts create mode 100644 out/@types/flush.d.ts create mode 100644 out/@types/main.d.ts create mode 100644 out/@types/nextLoop.d.ts create mode 100644 out/@types/queue.d.ts create mode 100644 out/@types/scheduler.d.ts create mode 100644 out/@types/slice.d.ts create mode 100644 out/@types/typedef.d.ts create mode 100644 out/batching.js create mode 100644 out/flush.js create mode 100644 out/main.js create mode 100644 out/nextLoop.js create mode 100644 out/queue.js create mode 100644 out/scheduler.js create mode 100644 out/slice.js create mode 100644 out/typedef.js diff --git a/.gitignore b/.gitignore index 205089a..861e3ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ node_modules/ -out/ + package-lock.json .DS_Store diff --git a/out/@types/batching.d.ts b/out/@types/batching.d.ts new file mode 100644 index 0000000..88b55a8 --- /dev/null +++ b/out/@types/batching.d.ts @@ -0,0 +1,15 @@ +import { ExecutionCallback } from "./typedef"; +/** + * resume 重新开始 + */ +export declare function resumeExecutionCallback(): void; +/** + * pause 暂停执行 + */ +export declare function pauseExecutionCallback(): void; +/** + * false -> 执行中 + * @returns bool + */ +export declare function hasInExecution(): boolean; +export declare function runWithBatchingExecution(callback: ExecutionCallback): void; diff --git a/out/@types/flush.d.ts b/out/@types/flush.d.ts new file mode 100644 index 0000000..7515711 --- /dev/null +++ b/out/@types/flush.d.ts @@ -0,0 +1,2 @@ +export declare function flushCurrentCallback(): void; +export declare function nextLoopFlushCallbackQueue(): void; diff --git a/out/@types/main.d.ts b/out/@types/main.d.ts new file mode 100644 index 0000000..5c1040a --- /dev/null +++ b/out/@types/main.d.ts @@ -0,0 +1,3 @@ +import { ExecutionCallback } from "./typedef"; +export declare function nextTick(fn: ExecutionCallback): void; +export default nextTick; diff --git a/out/@types/nextLoop.d.ts b/out/@types/nextLoop.d.ts new file mode 100644 index 0000000..a2c102e --- /dev/null +++ b/out/@types/nextLoop.d.ts @@ -0,0 +1,2 @@ +export declare function requestNextLoopExecutionCallback(): void; +export declare function nextLoopPauseExecution(): void; diff --git a/out/@types/queue.d.ts b/out/@types/queue.d.ts new file mode 100644 index 0000000..5c318c0 --- /dev/null +++ b/out/@types/queue.d.ts @@ -0,0 +1,6 @@ +import { ExecutionCallback } from "./typedef"; +interface Queue { + nextCallbackQueue: ExecutionCallback[]; +} +export declare const callbackQueue: Queue; +export {}; diff --git a/out/@types/scheduler.d.ts b/out/@types/scheduler.d.ts new file mode 100644 index 0000000..979f525 --- /dev/null +++ b/out/@types/scheduler.d.ts @@ -0,0 +1,2 @@ +import { ExecutionCallback } from "./typedef"; +export declare function schedulerOnCallbackExecution(fn: ExecutionCallback): void; diff --git a/out/@types/slice.d.ts b/out/@types/slice.d.ts new file mode 100644 index 0000000..744eaa2 --- /dev/null +++ b/out/@types/slice.d.ts @@ -0,0 +1,2 @@ +export declare function markStartTime(): void; +export declare function shouldYieldWithStart(): boolean; diff --git a/out/@types/typedef.d.ts b/out/@types/typedef.d.ts new file mode 100644 index 0000000..dd1ade2 --- /dev/null +++ b/out/@types/typedef.d.ts @@ -0,0 +1,3 @@ +export interface ExecutionCallback { + (): void; +} diff --git a/out/batching.js b/out/batching.js new file mode 100644 index 0000000..064ca72 --- /dev/null +++ b/out/batching.js @@ -0,0 +1,31 @@ +let BatchingExecution = true; +/** + * resume 重新开始 + */ +export function resumeExecutionCallback() { + BatchingExecution = true; +} +/** + * pause 暂停执行 + */ +export function pauseExecutionCallback() { + BatchingExecution = false; +} +/** + * false -> 执行中 + * @returns bool + */ +export function hasInExecution() { + return BatchingExecution; +} +export function runWithBatchingExecution(callback) { + try { + const next = hasInExecution(); + if (next) { + return callback(); + } + } + finally { + pauseExecutionCallback(); + } +} diff --git a/out/flush.js b/out/flush.js new file mode 100644 index 0000000..b804ccd --- /dev/null +++ b/out/flush.js @@ -0,0 +1,53 @@ +import { resumeExecutionCallback } from "./batching"; +import { requestNextLoopExecutionCallback } from "./nextLoop"; +import { callbackQueue } from "./queue"; +import { markStartTime, shouldYieldWithStart } from "./slice"; +let currentCallbackQueue = null; +function requestCurrentQueue() { + if (currentCallbackQueue !== null) { + return currentCallbackQueue; + } + if (callbackQueue.nextCallbackQueue.length > 0) { + currentCallbackQueue = callbackQueue.nextCallbackQueue; + callbackQueue.nextCallbackQueue = []; + return currentCallbackQueue; + } + return null; +} +function shouldNextLoop() { + if (currentCallbackQueue !== null) { + return true; + } + if (callbackQueue.nextCallbackQueue.length > 0) { + return true; + } + return false; +} +export function flushCurrentCallback() { + markStartTime(); + let queue = requestCurrentQueue(); + if (queue === null) { + return; + } + let s = Date.now(); + while (queue.length > 0 && !shouldYieldWithStart()) { + let callback = queue.shift(); + callback(); + } + let s2 = Date.now(); + console.log(s2 - s, currentCallbackQueue.length, "暂定执行执行终端", "nextLoopFlushCallbackQueue"); + if (queue.length === 0) { + currentCallbackQueue = null; + } +} +export function nextLoopFlushCallbackQueue() { + flushCurrentCallback(); + // 队列不为空, 我希望在下一轮循环中执行他们 + if (shouldNextLoop()) { + requestNextLoopExecutionCallback(); + } + else { + // 本轮循环中立即关闭,否增,下一轮循环关闭时会存在未被执行的回调函数 + resumeExecutionCallback(); + } +} diff --git a/out/main.js b/out/main.js new file mode 100644 index 0000000..137c976 --- /dev/null +++ b/out/main.js @@ -0,0 +1,5 @@ +import { schedulerOnCallbackExecution } from "./scheduler"; +export function nextTick(fn) { + schedulerOnCallbackExecution(fn); +} +export default nextTick; diff --git a/out/nextLoop.js b/out/nextLoop.js new file mode 100644 index 0000000..d92284e --- /dev/null +++ b/out/nextLoop.js @@ -0,0 +1,11 @@ +import { nextLoopFlushCallbackQueue } from "./flush"; +import { pauseExecutionCallback } from "./batching"; +const channel = new MessageChannel(); +channel.port1.onmessage = nextLoopFlushCallbackQueue; +channel.port2.onmessage = pauseExecutionCallback; +export function requestNextLoopExecutionCallback() { + channel.port2.postMessage(null); +} +export function nextLoopPauseExecution() { + channel.port1.postMessage(null); +} diff --git a/out/queue.js b/out/queue.js new file mode 100644 index 0000000..7f9ba68 --- /dev/null +++ b/out/queue.js @@ -0,0 +1,5 @@ +export const callbackQueue = { + nextCallbackQueue: [] +}; +// 使用链表来做 +// 支持ms diff --git a/out/scheduler.js b/out/scheduler.js new file mode 100644 index 0000000..7b34549 --- /dev/null +++ b/out/scheduler.js @@ -0,0 +1,7 @@ +import { runWithBatchingExecution } from "./batching"; +import { requestNextLoopExecutionCallback } from "./nextLoop"; +import { callbackQueue } from "./queue"; +export function schedulerOnCallbackExecution(fn) { + callbackQueue.nextCallbackQueue.push(fn); + runWithBatchingExecution(requestNextLoopExecutionCallback); +} diff --git a/out/slice.js b/out/slice.js new file mode 100644 index 0000000..6f2ee34 --- /dev/null +++ b/out/slice.js @@ -0,0 +1,13 @@ +let _startTime = null; +export function markStartTime() { + _startTime = Date.now(); +} +export function shouldYieldWithStart() { + let end = Date.now(); + let step = end - _startTime; + if (step > 80) { + _startTime = end; + return true; + } + return false; +} diff --git a/out/typedef.js b/out/typedef.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/out/typedef.js @@ -0,0 +1 @@ +export {}; diff --git a/package.json b/package.json index eb6f058..f16b48f 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,9 @@ "version": "0.0.1", "description": "next event loop, execute callback function before setTimeout", "types": "./typedef.d.ts", - "main": "src/main.ts", - "module": "src/main.ts", - "browser": "src/main.ts", + "main": "out/main.js", + "module": "out/main.js", + "browser": "out/main.js", "scripts": { "tsc":"tsc" diff --git a/tsconfig.json b/tsconfig.json index c683d79..695ecc1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "baseUrl": ".", "declaration": true, + "noEmit": false, "target": "ESNext", "declarationDir": "./out/@types", "outDir": "./out" From eb64e9ea51ed0b7269f759b6e4b10033188882aa Mon Sep 17 00:00:00 2001 From: HXY Date: Thu, 23 Nov 2023 13:44:48 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E5=88=A0=E9=99=A4loglog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- out/flush.js | 3 --- src/flush.ts | 4 ---- 2 files changed, 7 deletions(-) diff --git a/out/flush.js b/out/flush.js index b804ccd..90e57b4 100644 --- a/out/flush.js +++ b/out/flush.js @@ -29,13 +29,10 @@ export function flushCurrentCallback() { if (queue === null) { return; } - let s = Date.now(); while (queue.length > 0 && !shouldYieldWithStart()) { let callback = queue.shift(); callback(); } - let s2 = Date.now(); - console.log(s2 - s, currentCallbackQueue.length, "暂定执行执行终端", "nextLoopFlushCallbackQueue"); if (queue.length === 0) { currentCallbackQueue = null; } diff --git a/src/flush.ts b/src/flush.ts index e27d816..fa50d30 100644 --- a/src/flush.ts +++ b/src/flush.ts @@ -38,15 +38,11 @@ export function flushCurrentCallback() { return; } - let s = Date.now(); - while (queue.length > 0 && !shouldYieldWithStart()) { let callback = queue.shift(); callback(); } - let s2 = Date.now(); - console.log(s2 - s, currentCallbackQueue.length, "暂定执行执行终端", "nextLoopFlushCallbackQueue"); if (queue.length === 0) { currentCallbackQueue = null; }