Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

node_modules/

package-lock.json

.DS_Store
bun.lockb
15 changes: 15 additions & 0 deletions out/@types/batching.d.ts
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 2 additions & 0 deletions out/@types/flush.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export declare function flushCurrentCallback(): void;
export declare function nextLoopFlushCallbackQueue(): void;
3 changes: 3 additions & 0 deletions out/@types/main.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ExecutionCallback } from "./typedef";
export declare function nextTick(fn: ExecutionCallback): void;
export default nextTick;
2 changes: 2 additions & 0 deletions out/@types/nextLoop.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export declare function requestNextLoopExecutionCallback(): void;
export declare function nextLoopPauseExecution(): void;
6 changes: 6 additions & 0 deletions out/@types/queue.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ExecutionCallback } from "./typedef";
interface Queue {
nextCallbackQueue: ExecutionCallback[];
}
export declare const callbackQueue: Queue;
export {};
2 changes: 2 additions & 0 deletions out/@types/scheduler.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { ExecutionCallback } from "./typedef";
export declare function schedulerOnCallbackExecution(fn: ExecutionCallback): void;
2 changes: 2 additions & 0 deletions out/@types/slice.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export declare function markStartTime(): void;
export declare function shouldYieldWithStart(): boolean;
3 changes: 3 additions & 0 deletions out/@types/typedef.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface ExecutionCallback {
(): void;
}
31 changes: 31 additions & 0 deletions out/batching.js
Original file line number Diff line number Diff line change
@@ -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();
}
}
50 changes: 50 additions & 0 deletions out/flush.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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;
}
while (queue.length > 0 && !shouldYieldWithStart()) {
let callback = queue.shift();
callback();
}
if (queue.length === 0) {
currentCallbackQueue = null;
}
}
export function nextLoopFlushCallbackQueue() {
flushCurrentCallback();
// 队列不为空, 我希望在下一轮循环中执行他们
if (shouldNextLoop()) {
requestNextLoopExecutionCallback();
}
else {
// 本轮循环中立即关闭,否增,下一轮循环关闭时会存在未被执行的回调函数
resumeExecutionCallback();
}
}
5 changes: 5 additions & 0 deletions out/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { schedulerOnCallbackExecution } from "./scheduler";
export function nextTick(fn) {
schedulerOnCallbackExecution(fn);
}
export default nextTick;
11 changes: 11 additions & 0 deletions out/nextLoop.js
Original file line number Diff line number Diff line change
@@ -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);
}
5 changes: 5 additions & 0 deletions out/queue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const callbackQueue = {
nextCallbackQueue: []
};
// 使用链表来做
// 支持ms
7 changes: 7 additions & 0 deletions out/scheduler.js
Original file line number Diff line number Diff line change
@@ -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);
}
13 changes: 13 additions & 0 deletions out/slice.js
Original file line number Diff line number Diff line change
@@ -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;
}
1 change: 1 addition & 0 deletions out/typedef.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {};
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "next-tick",
"version": "0.0.1",
"description": "next event loop, execute callback function before setTimeout",
"types": "./typedef.d.ts",
"main": "out/main.js",
"module": "out/main.js",
"browser": "out/main.js",

"scripts": {
"tsc":"tsc"
},
"repository": {
"type": "git",
"url": "https://github.com/lsxqXs/next-tick.git"
},
"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",
"devDependencies": {
"typescript": "^4.6.4"
},
"files": [
"README.md",
"index.d.ts",
"out"
]
}
40 changes: 40 additions & 0 deletions src/batching.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

import { ExecutionCallback } from "./typedef";

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: ExecutionCallback) {
try {
const next = hasInExecution();
if (next) {
return callback();
}
} finally {
pauseExecutionCallback();
}
}

64 changes: 64 additions & 0 deletions src/flush.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
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;
}

while (queue.length > 0 && !shouldYieldWithStart()) {
let callback = queue.shift();
callback();
}

if (queue.length === 0) {
currentCallbackQueue = null;
}
}

export function nextLoopFlushCallbackQueue() {

flushCurrentCallback();

// 队列不为空, 我希望在下一轮循环中执行他们
if (shouldNextLoop()) {
requestNextLoopExecutionCallback();
}
else {
// 本轮循环中立即关闭,否增,下一轮循环关闭时会存在未被执行的回调函数
resumeExecutionCallback();
}

}
10 changes: 10 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

import {ExecutionCallback} from "./typedef";
import { schedulerOnCallbackExecution } from "./scheduler";


export function nextTick(fn:ExecutionCallback) {
schedulerOnCallbackExecution(fn);
}

export default nextTick;
15 changes: 15 additions & 0 deletions src/nextLoop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
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);
}
15 changes: 15 additions & 0 deletions src/queue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

import {ExecutionCallback} from "./typedef";



interface Queue {
nextCallbackQueue: ExecutionCallback[];
}

export const callbackQueue: Queue = {
nextCallbackQueue: []
};

// 使用链表来做
// 支持ms
10 changes: 10 additions & 0 deletions src/scheduler.ts
Original file line number Diff line number Diff line change
@@ -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);
}
Loading