A channel represents a method for receiving messages from the outside world.
Represents a method for receiving messages from the outside world.
You can define a channel that simply listens for messages on a subscription.
join : ((a -> msg) -> Platform.Sub.Sub msg) -> Channel a msg
Define a channel by providing a subscription to receive messages.
For example, you might want to listen for key presses but only send certain ones to your update function. You could accomplish that like so:
Channel.join (\tagger ->
Decode.map tagger keyDecoder
|> Browser.Events.onKeyPress
)
|> Channel.filter (\_ keyPress ->
keyPress == "Z"
|| keyPress == "X"
|| keyPress == "Y"
)
|> Channel.acceptUntil (\_ -> False)
|> Procedure.run ProcMsg PressedKey
String
Represents the unique key assigned to each procedure.
This is most useful when opening a channel by sending a command, where you might pass the key through a port and then use it to filter incoming messages to a subscription.
Represents a request to open a channel.
open : (ChannelKey -> Platform.Cmd.Cmd msg) -> ChannelRequest msg
Open a channel by sending a command. Use this in conjunction with connect
to define a channel.
For example, you might need to send a command over a port and then wait for a response via a port subscription. You could accomplish that like so:
Channel.open (\_ -> myPortCommand)
|> Channel.connect myPortSubscription
|> Channel.acceptOne
|> Procedure.run ProcedureTagger DataTagger
Use the provided ChannelKey
if you need something to connect subscription messages with the command that opens the channel.
On the JS side, your port command could take the channel key and pass it back when supplying a subscription message.
In your channel setup, you would filter messages by this key. See filter
for an example.
connect : ((a -> msg) -> Platform.Sub.Sub msg) -> ChannelRequest msg -> Channel a msg
Define a channel by providing a subscription to receive messages after
you use open
to send a command that opens a channel.
filter : (ChannelKey -> a -> Basics.Bool) -> Channel a msg -> Channel a msg
Filter messages received by whatever subscription is listening on this channel.
For example, you might need to send a command over a port and then wait for a response via a port subscription. You could accomplish that like so:
Channel.open (\key -> myPortCommand key)
|> Channel.connect myPortSubscription
|> Channel.filter (\key data -> data.key == key)
|> Channel.acceptOne
|> Procedure.run ProcedureTagger DataTagger
In this example, we pass the channel key through the port and use it to filter incoming subscription messages. This allows us to associate the messages we receive with a particular channel (and procedure), in case multiple procedures with channels that utilize this subscription are running simultaneously.
Note: Calling filter multiple times on a channel simply replaces any existing filter on that channel.
accept : Channel a msg -> Procedure.Internal.Procedure e a msg
Generate a procedure that processes messages on a channel indefinitely.
For example, suppose mySubscription
provides a stream of numbers. If you wanted to filter and map
these messages before passing these to your update function, you could do the following:
Channel.join mySubscription
|> Channel.filter (\_ data -> modBy 2 data == 0)
|> Channel.accept
|> Procedure.map String.fromInt
|> Procedure.run ProcedureTagger StringTagger
Then, as numbers come in through mySubscription
, a StringTagger
message will be sent
that tags the even numbers as a string.
acceptOne : Channel a msg -> Procedure.Internal.Procedure e a msg
Generate a procedure that accepts the first message to be processed from a channel. After that message is processed, the channel is closed.
For example, if you wanted to send a request via a port command and wait for a response on some port subscription, you could do the following:
Channel.open (\_ -> myPortCommand)
|> Channel.connect myPortSubscription
|> Channel.acceptOne
|> Procedure.run ProcedureTagger DataTagger
acceptUntil : (a -> Basics.Bool) -> Channel a msg -> Procedure.Internal.Procedure e a msg
Generate a procedure that processes messages on a channel as they are received until the predicate is satisfied. When the predicate is satisfied, the last message received on the channel will be processed and the channel will be closed.
For example, suppose mySubscription
provides a stream of numbers. If you wanted to filter and map
these messages before passing these to your update function, you could do the following:
Channel.join mySubscription
|> Channel.filter (\_ data -> modBy 2 data == 0)
|> Channel.acceptUntil (\data -> data == 20)
|> Procedure.map String.fromInt
|> Procedure.run ProcedureTagger StringTagger
Then, as numbers come in through mySubscription
, a StringTagger
message will be sent
that tags the number as a string. Once the number 20
is received from the subscription, the
channel will close and process no more messages. The last message sent by this procedure will
be StringTagger "20"
.