abbr / deasync

Turns async function into sync via JavaScript wrapper of Node event loop
MIT License
971 stars 73 forks source link

Worker + SharedArrayBuffer alternative #177

Open jimmywarting opened 1 year ago

jimmywarting commented 1 year ago

Looking trough the issue i see that there are a bunch of gyp, electron and loop / freezes and high cpu issues floating around.

What i was looking for was a solution that did not only works in nodejs but also works for other env. too. like Deno, Bun.js and heck even web workers.

And there where basically nothing out there what i could find. everything is so NodeJS specific or poorly implemented that uses eg child processes or worker_threads, so transferring data to other threads where very limited.

So now i introduce to you: await-sync

Here it's in its simplest form:

import { createWorker } from 'to-sync'

const awaitSync = createWorker()

const get = awaitSync(async url => {
  const res = await fetch(url)
  const ab = await res.arrayBuffer()
  return new Uint8Array(ab)
})

const uint8 = get('https://httpbin.org/get') // Uint8Array

Using this solution will:

  1. spin up a new Worker,
  2. transfer the function stringifyed code to that worker
  3. and once you call the get fn, a postMessage is sent to the worker with all the arguments and the current thread will freeze using Atomic.wait()... The entire event loop is halted.
  4. only the worker can unfreeze it now. now the worker instead dose all the work async.
  5. and to achieve transferring the content back to the thread without using onmessage or even using worker.receiveMessageOnPort(port) which isn't so cross env. friendly btw... is achived using only SharedArrayBuffer + Atomic dance.