Effect.Aff.Link
- Package
- purescript-workly
- Repository
- cakekindel/purescript-workly
Module containing Channels for communicating across Worker thread boundaries
> -- setup required to run examples
> import Effect.Aff.Link
> import Effect (Effect)
> import Effect.Unsafe (unsafePerformEffect)
> import Effect.Aff (Aff)
> import Test.Deasync (unsafeBlockOnAff)
> runAff = unsafeBlockOnAff
> runEff = unsafePerformEffect
#send Source
send :: forall u. u -> Link u _ -> Aff Unit
Send a message in the uplink channel of a Link
.
> sendExUp :: Channel String
sendExUp = runAff newChannel
> sendExDown :: Channel Unit
sendExDown = runAff newChannel
> sendEx = Link {up: sendExUp, down: sendExDown}
> runAff $ send "here's a message!" sendEx
unit
> -- now whoever's upstream will get our message
#recv Source
recv :: forall d. Link _ d -> Aff d
Blocks until a message is available in the downlink channel of a Link
.
Once a message is available, clears the downlink channel and yields the message.
> recvExUp :: Channel Unit
recvExUp = runAff newChannel
> recvExDown :: Channel String
recvExDown = runAff newChannel
> recvEx = Link {up: recvExUp, down: recvExDown}
> -- emulate a message being sent by someone upstream
> runAff $ put "hello!" recvExDown
unit
> runAff $ recv recvEx
"hello!"
#Channel Source
data Channel a
A one-way channel storing some mutable state a
,
capable of performing side-effects on update (such as Worker#postMessage
).
Is very similar to the AVar
structure from purescript-avar
,
but allows attaching change listeners which allows JS-style event listeners
to be used as data sources.
Can be constructed with newChannelFromCb
, newChannel
, newChannelHot
.
#snap Source
snap :: forall a. Channel a -> Aff (Maybe a)
Get a snapshot of the value in a Channel
directional channel.
Similar to read
, but returns Nothing
if there is no
value in the channel, rather than blocking until a value exists.
> snapEx :: Channel String
snapEx = runAff newChannel
> runAff $ put "testing" snapEx
unit
> runAff $ snap snapEx
(Just "testing")
> runAff $ take snapEx
"testing"
> runAff $ snap snapEx
Nothing
#put Source
put :: forall a. a -> Channel a -> Aff Unit
Discard any value currently in the Channel
and insert
a new one.
This will notify all listeners of an update, triggering
any necessary side-effects (such as Worker#postMessage
)
Wait for a value to be inserted into the Channel
,
then yield it and empty the Channel
.
> putEx :: Channel String
putEx = runAff $ newChannel
> runAff $ snap putEx
Nothing
> runAff $ put "testing" putEx
unit
> runAff $ snap putEx
(Just "testing")
> runAff $ put "testing2" putEx
unit
> runAff $ read putEx
"testing2"
#read Source
read :: forall a. Channel a -> Aff a
Wait for a value to be inserted into a channel, then yield it without modifying the state.
> readEx :: Channel Int
readEx = runAff newChannel
-- danger!
-- reading now will block forever since nobody will
-- `put` a value in the channel!
> runAff $ put 123 readEx
unit
> runAff $ read readEx
123
> runAff $ read readEx
123
#newChannel Source
newChannel :: forall a. Aff (Channel a)
Create a new empty one-way channel, with empty initial state.
Calls to read
or take
will block until a value is inserted.
> numChannel :: Channel Int
numChannel = runAff newChannel
> runAff $ put 12 numChannel
unit
> runAff $ read numChannel
12
#newChannelHot Source
newChannelHot :: forall a. ImpureCb a -> Aff (Channel a)
Create a one-way channel that invokes some callback when a message is put into the channel.
> import Effect.Ref as Ref
> -- set up a piece of mutable state to demo performing
> -- side-effects on `put`
> didPut = runEff $ Ref.new false
> setDidPut :: String -> Effect Unit
setDidPut _ = Ref.modify_ (const true) didPut
> onPutEx :: Channel String
onPutEx = runAff $ newChannelHot setDidPut
> runAff $ put "testing" onPutEx
unit
> runEff $ Ref.read didPut
true
#newChannelFromCb Source
newChannelFromCb :: forall a. AttachImpureCb a -> Aff (Channel a)
Create a one-way channel that sources its data from an asynchronous (JS) callback.
> import Effect.Ref (Ref)
> import Effect.Ref as R
> -- create a mutable ref to mimic JS code
-- attaching a callback to an async source
> cbRef :: Ref (String -> Effect Unit)
cbRef = runEff $ R.new \_ -> mempty
> setCb = \cb -> R.modify_ (const cb) cbRef
> -- create a channel that gives our "JS" code
-- a callback to invoke
> cbEx = runAff $ newChannelFromCb setCb
> -- invoke the callback
> cb = runEff $ R.read cbRef
> runEff $ cb "hello"
unit
> runAff $ snap cbEx
(Just "hello")