base-x icon indicating copy to clipboard operation
base-x copied to clipboard

Async api

Open Ayzrian opened this issue 5 years ago • 4 comments

Hi! It would be great if this lib could expose async api, because sometimes it can block js significantly.

Ayzrian avatar Feb 14 '20 14:02 Ayzrian

If it blocks for you then use workers.

zdila avatar Aug 28 '20 10:08 zdila

async ?? how would that even work ? (other than workers as suggested by @zdila )

sublimator avatar Aug 28 '20 11:08 sublimator

Although it's not hard to build a worker around, it would be nice to have it as a build-in feature. I'm using this to process around 50KB of data which takes more than 10 seconds.

If someone's looking for a simple worker wrapper, this is my TypeScript code:

import * as baseX from 'base-x';

export type BaseX_WorkerMessage =
  { type: 'encode', alphabet: string, buffer: Buffer | number[] | Uint8Array } |
  { type: 'decode', alphabet: string, data: string }
  ;

// We alias self to ctx and give it our newly created type
const ctx: Worker = self as any;    // NOTE: this ugly comes from here: https://www.jameslmilner.com/post/workers-with-webpack-and-typescript/

ctx.addEventListener('message', message  => {
  const data: BaseX_WorkerMessage = message.data;
  switch (data.type) {
    case 'encode': return ctx.postMessage(baseX(data.alphabet).encode(data.buffer));
    case 'decode': return ctx.postMessage(baseX(data.alphabet).decode(data.data));
  }
});

And if you want to call something you can await, you can build universal worker executor:

import WebpackWorker from 'worker-loader!*';

// Simple Promise wrapper around a worker. It takes a worker constructor, it builds one, send it a message and resolves with whatever worker returns. Afterwards worker is terminated.
export function executeWorker<RESULT, MESSAGE>(getWorker: typeof WebpackWorker, message: MESSAGE): Promise<RESULT> {
  const worker = getWorker();
  return new Promise<RESULT>((resolve, reject) => {
    worker.postMessage(message);
    worker.onmessageerror = reject;
    worker.onerror = reject;
    worker.onmessage = e => resolve(e.data);
  }).finally(() => worker.terminate());
}

Juraj-Masiar avatar Aug 28 '20 11:08 Juraj-Masiar

the async api that he want should be just like React Fiber

(async () => {
  // do all work
  for (let i = 0; i <= 10000; i++) {
    if (i % 500 == 0) {
      await new Promise((res) => {
        setTimeout(res);
      });
    }
    // do batch work
  }
})();

lisonge avatar Aug 22 '22 03:08 lisonge

Unclear as to what exactly you want. "Make it async" is too vague.

lisonge's idea seems reasonable. PRs welcome.

junderw avatar Feb 27 '23 15:02 junderw