permalinkuseWebWorker
Here's a Hook you can use with yoga-web-proletarian to create a Web Worker and send messages to it.
src/Hooks/UseWebworker.purs
-- use client
module Hooks.UseWebWorker where
import Prelude
import Data.Newtype (class Newtype)
import React.Basic.Hooks as React
import Yoga.WebBoss (onMessageFromWorker, postMessageToWorker, terminate)
import Yoga.WebProletarian.Types (Worker)
import Effect.AVar as AVar
import Effect.AVar (AVar)
import Effect.Aff.AVar as AffVar
import Effect.Aff (launchAff_)
import Effect.Class (liftEffect)
import Control.Promise (toAffE, Promise)
import React.Basic.Hooks (UseEffect, UseRef)
import Data.Maybe (Maybe, Maybe(..))
import Effect (Effect)
import React.Basic.Hooks.Internal (Hook, coerceHook)
import Data.Foldable (traverse_)
newtype UseWebWorker from to hooks = UseWebWorker
( UseEffect Unit
(UseRef (Maybe ({ worker ∷ Worker from to, mutex ∷ AVar Unit })) hooks)
)
derive instance Newtype (UseWebWorker from to hooks) _
useWebWorker
∷ ∀ toWorker fromWorker
. Effect (Promise (Worker toWorker fromWorker))
→ (fromWorker → Effect Unit)
→ Hook (UseWebWorker toWorker fromWorker) (toWorker → Effect Unit)
useWebWorker newWorker handler = coerceHook React.do
workerRef ← React.useRef Nothing
React.useEffectOnce do
launchAff_ do
worker ← newWorker # toAffE
mutex ← AffVar.new unit
liftEffect $ worker # onMessageFromWorker \msg → launchAff_ do
handler msg # liftEffect
AffVar.put unit mutex
React.writeRef workerRef (Just { worker, mutex }) # liftEffect
pure do
React.readRef workerRef >>=
(traverse_ \{ worker, mutex } → terminate worker)
pure \msg → do
React.readRef workerRef
>>= traverse_
\{ worker, mutex } → launchAff_ do
AffVar.take mutex
postMessageToWorker msg worker # liftEffect