Skip to content

asyncLoop is not working as intended #113

@ChALkeR

Description

@ChALkeR

noble-hashes/src/utils.ts

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++);})

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions