miso
Copyright(C) 2016-2026 David M. Johnson
LicenseBSD3-style (see the file LICENSE)
MaintainerDavid M. Johnson <code@dmj.io>
Stabilityexperimental
Portabilitynon-portable
Safe HaskellNone
LanguageHaskell2010

Miso.PubSub

Contents

Description

Overview

Miso.PubSub provides a lightweight publish/subscribe channel for passing messages between independent Component trees that do not share a parent-child relationship.

A Topic is an untyped broadcast channel. Any component can publish a message to it; every component that has called subscribe on that topic will receive the message as an action.

Quick start

import Miso
import Miso.PubSub

-- 1. Create a shared topic (typically at the top level or in a shared module)
chatTopic :: IO Topic
chatTopic = topic

-- 2. Subscribe in a component's subs list
myChatSub :: Topic -> Sub Action
myChatSub t = subscribe t GotMessage

-- 3. Publish from any component's update function
update :: Action -> Effect p props Model Action
update (SendMessage msg) =
  io_ (publish chatTopic msg)
update (GotMessage msg) = do
  ...

API

  • topic — create a new broadcast channel
  • subscribe — register a component subscription that receives published values
  • unsubscribe — deregister a subscription
  • publish — broadcast a value to all current subscribers

See also

Synopsis

Pub/Sub

data Topic a Source #

A Topic represents a place to send and receive messages. Topic is used to facilitate communication between Component. Component can subscribe to or publish to any Topic, within the same Component or across Component.

This requires creating a custom ToJSON / FromJSON. Any other Component can publish or subscribe to this Topic message. It is a way to provide loosely-coupled communication between Components.

See publish, subscribe, unsubscribe for more details.

When distributing Component for third-party use, it is recommended to export the Topic, where message is the JSON protocol.

Since: 1.9.0.0

Instances

Instances details
Show (Topic a) Source # 
Instance details

Defined in Miso.Runtime

Methods

showsPrec :: Int -> Topic a -> ShowS #

show :: Topic a -> String #

showList :: [Topic a] -> ShowS #

Eq (Topic a) Source # 
Instance details

Defined in Miso.Runtime

Methods

(==) :: Topic a -> Topic a -> Bool #

(/=) :: Topic a -> Topic a -> Bool #

Ord (Topic a) Source # 
Instance details

Defined in Miso.Runtime

Methods

compare :: Topic a -> Topic a -> Ordering #

(<) :: Topic a -> Topic a -> Bool #

(<=) :: Topic a -> Topic a -> Bool #

(>) :: Topic a -> Topic a -> Bool #

(>=) :: Topic a -> Topic a -> Bool #

max :: Topic a -> Topic a -> Topic a #

min :: Topic a -> Topic a -> Topic a #

ToMisoString (Topic a) Source # 
Instance details

Defined in Miso.Runtime

topic :: MisoString -> Topic a Source #

Smart constructor for creating a Topic message to write to

data Message
  = Increment
  | Decrement
  deriving (Show, Eq, Generic, ToJSON, FromJSON)

arithmetic :: Topic Message
arithmetic = topic "arithmetic"

data Action
  = Notification (Result Message)
  | Subscribe
  | Unsubscribe

update_ :: Action -> Effect parent props Int Action
update_ = case
  Unsubscribe ->
    unsubscribe arithmetic
  Subscribe ->
    subscribe arithmetic Notification
  Notification (Success Increment) ->
    update_ AddOne
  Notification (Success Decrement) ->
    update_ SubtractOne
  Notification (Error msg) ->
    io_ $ consoleError ("Decode failure: " <> ms msg)

Since: 1.9.0.0

subscribe :: FromJSON message => Topic message -> (message -> action) -> (MisoString -> action) -> Effect parent props model action Source #

Subscribes a Component to a Topic.

Registers a callback in the component that decodes incoming messages using its own FromJSON instance and dispatches them to the component's Sink. If the component is already subscribed to the named topic the previous callback is replaced.

Because each subscriber uses its own FromJSON, components can use different Haskell types for the same topic as long as the underlying JSON is compatible, enabling loose coupling between Component.

data Message = Increment | Decrement
  deriving (Show, Eq, Generic, ToJSON, FromJSON)

arithmetic :: Topic Message
arithmetic = topic "arithmetic"

data Action
  = Notify Message
  | NotifyError MisoString
  | Subscribe
  | Unsubscribe
  | AddOne
  | SubtractOne

update_ :: Action -> Effect parent props Int Action
update_ = \case
  Subscribe ->
    subscribe arithmetic Notify NotifyError
  Unsubscribe ->
    unsubscribe arithmetic
  Notify Increment -> update_ AddOne
  Notify Decrement -> update_ SubtractOne
  NotifyError msg ->
    io_ $ consoleError ("Decode failure: " <> msg)
  AddOne -> _count += 1
  SubtractOne -> _count -= 1

Since: 1.9.0.0

unsubscribe :: Topic message -> Effect parent props model action Source #

Unsubscribes a Component from a Topic.

Removes the callback registered by subscribe so the component no longer receives messages published to the topic. If the component is not currently subscribed this is a no-op.

See subscribe for example usage.

Since: 1.9.0.0

publish :: ToJSON message => Topic message -> message -> IO () Source #

Publish to a t'Topic message'

t'Topic message' are generated dynamically if they do not exist. When using publish all subscribers are immediately notified of a new message. A message is distributed as a Value The underlying ToJSON instance is used to construct this Value.

We recommend documenting a public API for the JSON protocol message when distributing a Component downstream to end users for consumption (be it inside a single cabal project or across multiple cabal projects).

arithmetic :: Topic Message
arithmetic = topic "arithmetic"

server :: Component parent props () Action
server = component () update_ $ () ->
  div_
  []
  [ "Server component"
  , button_ [ onClick AddOne ] [ "+" ]
  , button_ [ onClick SubtractOne ] [ "-" ]
  , component_ (client_ "client 1")
  , component_ (client_ "client 2")
  ] where
      update_ :: Action -> Effect parent props () Action
      update_ = case
        AddOne ->
          publish arithmetic Increment
        SubtractOne ->
          publish arithemtic Decrement

Since: 1.9.0.0