#Passing around a web worker

14 messages · Page 1 of 1 (latest)

languid fern
#

Is there a good way to create a web worker and then have several different components call postMessage to it?

#

I guess I want to call new Worker(path) and then pass that around as a prop so that I can do worker.postMessage in various components' onclick handlers

#

looking at doing something like this ```js
export default component$(() => {
const store = useStore({
worker: null
})
// reg.passthrough();
useVisibleTask$(async () => {
if (isBrowser) {
const worker = new Worker("web-worker.js")
worker.addEventListener("message", () => {

  })
  store.worker = noSerialize(worker)
#

the issue I'm running into is that I can't initially set store to null, because then i get typescript errors when i try to set it to a Worker, but if I set it to a Worker, then ssr tries to use Worker where it isn't defined

languid fern
#

I've done the following to alleviate typescript errors, but am getting an Illegal Invocation error that I'll paste below as well

#
const store = useStore({
    postMessage: noSerialize((message: any) => {
      console.log({message})
    })
  })
  // reg.passthrough();
  useVisibleTask$(async () => {
    if (isBrowser) {
      const worker = new Worker("web-worker.js")
      worker.addEventListener("message", () => {
        console.log("main thread back")
      })
      store.postMessage = noSerialize(worker.postMessage)
      }

    }
  })
#

then i call it in my component as follows

#
export default component$((props: {postMessage: NoSerialize<(message: any) => void>}) => {
  const store = useStore({content: ""})
  console.log({store})
  return <>
    Data for updating
    <div>{store.content}</div>
    <button onClick$={() => {
      store.content = reg.getRegistryPass()
      const checkpoint = impGetCheckpoint()
      console.log({checkpoint})
      reg.update()
      // hashCheckpoint(checkpoint)
      console.log({props})
      if (props.postMessage) {
        // props.postMessage("")
        props.postMessage({type: "makeRequest"})
      }
    }
    }>Update</button>
  </>
})
#
q-e9ac06ab.js:1 Uncaught (in promise) TypeError: Illegal invocation
    at g (q-e9ac06ab.js:1:526)
    at f ((index):3:6536)
    at async HTMLDocument.p ((index):3:6840)
ancient raven
#

could using the file service-worker help you ?

languid fern
#

So i actually was able to work through this, but now I'm hitting another wall

#
export default component$(() => {
  const store = useStore({
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    postMessage: noSerialize(function (message: any) {
      console.log({message})
    })
  })
  // reg.passthrough();
  useVisibleTask$(async () => {
    if (isBrowser) {
      const worker = new Worker("web-worker.js", { type: "module" })
      worker.addEventListener("message", () => {
        console.log("main thread back")
      })
      store.postMessage = noSerialize(function(message: any) {
        worker.postMessage(message)
      })
      await $init
      window.localStorage.setItem("url", "http://127.0.0.1:8090")
    }
  })
#

I actually need to use a web worker instead of a service worker for my use case, but I also need to be able to import other files into my web worker, so I think I need to look into how the service-worker.js file is configured and bundled so that I can do that

#

May open another thread to ask about the new more specific question