Module

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 Channeldirectional 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

#take Source

take :: forall a. Channel a -> Aff a

Wait for a value to be inserted into the Channel, then yield it and empty the Channel.

> takeEx :: Channel Int
  takeEx = runAff newChannel
> runAff $ put 999 takeEx
unit
> runAff $ snap takeEx
(Just 999)
> runAff $ take takeEx
999
> runAff $ snap takeEx
Nothing

#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")

#ImpureCb Source

type ImpureCb a = a -> Effect Unit

#AttachImpureCb Source