-
-
Notifications
You must be signed in to change notification settings - Fork 60
Open
Description
Lines 183 to 205 in 9140c49
| /** | |
| * There is no setImmediate in browser and setTimeout is slow. | |
| * Call of async fn will return Promise, which will be fullfiled only on | |
| * next scheduler queue processing step and this is exactly what we need. | |
| */ | |
| export const nextTick = async (): Promise<void> => {}; | |
| /** Returns control to thread each 'tick' ms to avoid blocking. */ | |
| export async function asyncLoop( | |
| iters: number, | |
| tick: number, | |
| cb: (i: number) => void | |
| ): Promise<void> { | |
| let ts = Date.now(); | |
| for (let i = 0; i < iters; i++) { | |
| cb(i); | |
| // Date.now() is not monotonic, so in case if clock goes backwards we return return control too | |
| const diff = Date.now() - ts; | |
| if (diff >= 0 && diff < tick) continue; | |
| await nextTick(); | |
| ts += diff; | |
| } | |
| } |
This still hangs the page, try it out it devtools:
const nextTick = async () => {};
async function asyncLoop(iters, tick, cb) {
let ts = Date.now();
for (let i = 0; i < iters; i++) {
cb(i)
const diff = Date.now() - ts;
if (diff >= 0 && diff < tick) continue;
await nextTick();
ts += diff;
}
}
asyncLoop(1e5,10, () => {for (let j=0;j<1e7;j++);})Instead, use await globalThis.scheduler?.yield() when available
Support: https://caniuse.com/mdn-api_scheduler_yield
Doc: https://developer.mozilla.org/en-US/docs/Web/API/Scheduler/yield
Demo:
const nextTick = async () => {};
async function asyncLoop(iters, tick, cb) {
let ts = Date.now();
for (let i = 0; i < iters; i++) {
cb(i)
console.log('tick', i, Date.now())
if (globalThis.scheduler?.yield) {
await globalThis.scheduler.yield()
} else {
const diff = Date.now() - ts;
if (diff >= 0 && diff < tick) continue;
await nextTick();
ts += diff;
}
}
}
asyncLoop(1e5,10, () => {for (let j=0;j<1e7;j++);})Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels