-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added request-queue [todo] make it as a real package
- Loading branch information
Showing
13 changed files
with
535 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
pnpm-debug.log* | ||
lerna-debug.log* | ||
|
||
node_modules | ||
dist | ||
dist-ssr | ||
*.local | ||
|
||
# Editor directories and files | ||
.vscode/* | ||
!.vscode/extensions.json | ||
.idea | ||
.DS_Store | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln | ||
*.sw? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Vite + TS</title> | ||
</head> | ||
<body> | ||
<div id="app"></div> | ||
<script type="module" src="/src/main.ts"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"name": "request-queue", | ||
"private": true, | ||
"version": "0.0.0", | ||
"type": "module", | ||
"scripts": { | ||
"dev": "vite", | ||
"build": "tsc && vite build", | ||
"preview": "vite preview", | ||
"test": "ts-node ./tests/request.spec.ts" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^22.1.0", | ||
"typescript": "^5.2.2", | ||
"vite": "^5.3.4" | ||
}, | ||
"dependencies": { | ||
"ts-node": "^10.9.2" | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export function setupCounter(element: HTMLButtonElement) { | ||
let counter = 0 | ||
const setCounter = (count: number) => { | ||
counter = count | ||
element.innerHTML = `count is ${counter}` | ||
} | ||
element.addEventListener('click', () => setCounter(counter + 1)) | ||
setCounter(0) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import './style.css' | ||
import typescriptLogo from './typescript.svg' | ||
import viteLogo from '/vite.svg' | ||
import { setupCounter } from './counter.ts' | ||
|
||
document.querySelector<HTMLDivElement>('#app')!.innerHTML = ` | ||
<div> | ||
<a href="https://vitejs.dev" target="_blank"> | ||
<img src="${viteLogo}" class="logo" alt="Vite logo" /> | ||
</a> | ||
<a href="https://www.typescriptlang.org/" target="_blank"> | ||
<img src="${typescriptLogo}" class="logo vanilla" alt="TypeScript logo" /> | ||
</a> | ||
<h1>Vite + TypeScript</h1> | ||
<div class="card"> | ||
<button id="counter" type="button"></button> | ||
</div> | ||
<p class="read-the-docs"> | ||
Click on the Vite and TypeScript logos to learn more | ||
</p> | ||
</div> | ||
` | ||
|
||
setupCounter(document.querySelector<HTMLButtonElement>('#counter')!) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/** | ||
* RequestQueue is a class that manages a queue of requests. | ||
* It will execute requests parallelly maxing out at a certain number of requests at the same time. | ||
*/ | ||
|
||
export interface RequestQueueOptions { | ||
maxConcurrentRequests: number; | ||
ignoreNextFlush?: boolean; | ||
} | ||
|
||
export class RequestQueue { | ||
private __queue: any[] = []; | ||
private __maxConcurrentRequests!: number; | ||
|
||
private __next = false; | ||
private __pendingRequests = 0; | ||
private __ignoreNextFlush = false; | ||
|
||
constructor(options: RequestQueueOptions) { | ||
this.__maxConcurrentRequests = options.maxConcurrentRequests ?? 6; | ||
this.__queue = []; | ||
this.__pendingRequests = 0; | ||
this.__ignoreNextFlush = options.ignoreNextFlush ?? false; | ||
} | ||
|
||
private __eventMap = new Map<string, any>(); | ||
on(event: string, callback: any) { | ||
const eventCallbacks = this.__eventMap.get(event) ?? []; | ||
eventCallbacks.push(callback); | ||
this.__eventMap.set(event, eventCallbacks); | ||
} | ||
|
||
off(event: string, callback: any) { | ||
const eventCallbacks = this.__eventMap.get(event) ?? []; | ||
const newCallbacks = eventCallbacks.filter((cb: any) => cb !== callback); | ||
this.__eventMap.set(event, newCallbacks); | ||
} | ||
|
||
once(event: string, callback: any) { | ||
return new Promise((resolve) => { | ||
const onceCallback = async (data: any) => { | ||
await callback(data); | ||
resolve(undefined); | ||
this.off(event, onceCallback); | ||
}; | ||
this.on(event, onceCallback); | ||
}); | ||
} | ||
|
||
private __emit(event: string, data: any) { | ||
const eventCallbacks = this.__eventMap.get(event) ?? []; | ||
eventCallbacks.forEach((cb: any) => cb(data)); | ||
} | ||
|
||
/** | ||
* Add a request to the queue | ||
*/ | ||
insert(request: any) { | ||
this.__queue.push(request); | ||
this.__next = true; | ||
this.selfExecute(); | ||
} | ||
|
||
/** | ||
* Execute a request | ||
*/ | ||
private async selfExecute() { | ||
if (!this.__next) { | ||
return; | ||
} | ||
|
||
if (this.__queue.length === 0) { | ||
return; | ||
} | ||
|
||
if (this.__pendingRequests == this.__maxConcurrentRequests) { | ||
return; | ||
} | ||
|
||
const request = this.__queue.shift(); | ||
this.__pendingRequests++; | ||
await request(); | ||
this.__pendingRequests--; | ||
|
||
if ( | ||
this.__queue.length === 0 && | ||
this.__pendingRequests === 0 && | ||
!this.__ignoreNextFlush | ||
) { | ||
this.stop(); | ||
this.__emit('queueCompleted', null); | ||
return; | ||
} | ||
|
||
this.selfExecute(); | ||
} | ||
|
||
/** | ||
* Stop the queue | ||
*/ | ||
stop() { | ||
this.__next = false; | ||
} | ||
|
||
ignoreNextFlush(value: boolean) { | ||
this.__ignoreNextFlush = value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
:root { | ||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; | ||
line-height: 1.5; | ||
font-weight: 400; | ||
|
||
color-scheme: light dark; | ||
color: rgba(255, 255, 255, 0.87); | ||
background-color: #242424; | ||
|
||
font-synthesis: none; | ||
text-rendering: optimizeLegibility; | ||
-webkit-font-smoothing: antialiased; | ||
-moz-osx-font-smoothing: grayscale; | ||
} | ||
|
||
a { | ||
font-weight: 500; | ||
color: #646cff; | ||
text-decoration: inherit; | ||
} | ||
a:hover { | ||
color: #535bf2; | ||
} | ||
|
||
body { | ||
margin: 0; | ||
display: flex; | ||
place-items: center; | ||
min-width: 320px; | ||
min-height: 100vh; | ||
} | ||
|
||
h1 { | ||
font-size: 3.2em; | ||
line-height: 1.1; | ||
} | ||
|
||
#app { | ||
max-width: 1280px; | ||
margin: 0 auto; | ||
padding: 2rem; | ||
text-align: center; | ||
} | ||
|
||
.logo { | ||
height: 6em; | ||
padding: 1.5em; | ||
will-change: filter; | ||
transition: filter 300ms; | ||
} | ||
.logo:hover { | ||
filter: drop-shadow(0 0 2em #646cffaa); | ||
} | ||
.logo.vanilla:hover { | ||
filter: drop-shadow(0 0 2em #3178c6aa); | ||
} | ||
|
||
.card { | ||
padding: 2em; | ||
} | ||
|
||
.read-the-docs { | ||
color: #888; | ||
} | ||
|
||
button { | ||
border-radius: 8px; | ||
border: 1px solid transparent; | ||
padding: 0.6em 1.2em; | ||
font-size: 1em; | ||
font-weight: 500; | ||
font-family: inherit; | ||
background-color: #1a1a1a; | ||
cursor: pointer; | ||
transition: border-color 0.25s; | ||
} | ||
button:hover { | ||
border-color: #646cff; | ||
} | ||
button:focus, | ||
button:focus-visible { | ||
outline: 4px auto -webkit-focus-ring-color; | ||
} | ||
|
||
@media (prefers-color-scheme: light) { | ||
:root { | ||
color: #213547; | ||
background-color: #ffffff; | ||
} | ||
a:hover { | ||
color: #747bff; | ||
} | ||
button { | ||
background-color: #f9f9f9; | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/// <reference types="vite/client" /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { RequestQueue } from '../src/request-queue'; | ||
|
||
const requestQueue = new RequestQueue({ | ||
maxConcurrentRequests: 3, | ||
ignoreNextFlush: true, | ||
}); | ||
|
||
requestQueue.on('queueCompleted', () => { | ||
console.log('All requests finished'); | ||
}); | ||
|
||
const request = async (data: number) => { | ||
console.log(`Request started with data: ${data}`); | ||
await new Promise((resolve) => setTimeout(resolve, 1000)); | ||
console.log(`Request finished with data: ${data}`); | ||
}; | ||
|
||
Array.from({ length: 10 }, (_, i) => requestQueue.insert(() => request(i))); | ||
|
||
new Promise((resolve) => setTimeout(resolve, 13000)).then(() => { | ||
Array.from({ length: 4 }, (_, i) => requestQueue.insert(() => request(i))); | ||
requestQueue.ignoreNextFlush(false); | ||
}); | ||
|
||
// promise?.then(() => { | ||
// console.log('All requests finished'); | ||
// }); | ||
|
||
// requestQueue.pendingProcess?.then(() => { | ||
// console.log('All requests finished'); | ||
// }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"compilerOptions": { | ||
"target": "ES2020", | ||
"useDefineForClassFields": true, | ||
"module": "ESNext", | ||
"lib": [ | ||
"ESNext", | ||
"DOM", | ||
"DOM.Iterable" | ||
], | ||
"skipLibCheck": true, | ||
/* Bundler mode */ | ||
"moduleResolution": "Bundler", | ||
"allowImportingTsExtensions": true, | ||
"resolveJsonModule": true, | ||
"isolatedModules": true, | ||
"moduleDetection": "force", | ||
"noEmit": true, | ||
/* Linting */ | ||
"strict": true, | ||
"noUnusedParameters": true, | ||
"noFallthroughCasesInSwitch": true, | ||
"esModuleInterop": true, | ||
}, | ||
"include": [ | ||
"src", | ||
"tests" | ||
], | ||
"ts-node": { | ||
"esm": true, | ||
"experimentalSpecifierResolution": "node", | ||
} | ||
} |
Oops, something went wrong.