Examples

MessageChannel JSON exchange

Send ordinary JSON values through a local pair of native message ports.

Build and run

Requires Java 21+, Clojure CLI and the runtime named below. The example pins the compiler that supports native ^:async and await. Run these commands in a separate terminal from other examples.

git clone https://github.com/OUTCASTGEEK-TECH/fast-twitch.git
cd fast-twitch
git checkout a4eb73f96836d034c7a24fe09dc7d51e4c581f64
cd examples/07-native-transports
clojure -M:build ports
node target/ports.cjs

Expected result

The program prints MessageChannel with an explicit JSON codec passed after receiving the map {"values" [false nil 42]}.

Follow the ports

message-channel! creates both ports with :codec :json. The optional :on-event is attached to port2, so the program sends on port1. JSON encodes the ClojureScript value for the native port and decodes it into string-keyed maps at the receiver. The callback resolves a Promise with (:data event), not with the whole browser event object.

This is a local channel between contexts/ports; it is not TCP, an HTTP endpoint or persistent storage. Closing only port1 does not express ownership of port2. finally closes both handles, including the receiving port.

Exercises

Send a second value after arranging another consumer callback. Inspect :type, :data, :ports and the native event carrier in the event map. For a binary transferable use the native codec and an ArrayBuffer with {:transfer [buffer]}; ownership transfer means the sending context must stop using that buffer. The native codec does not automatically convert ClojureScript persistent maps into structured-clone objects; use native JavaScript data or select the JSON codec.

MessageChannel options · send! API.

Complete source and build files

The files below are copied without abbreviation from Fast-Twitch revision a4eb73f96836d034c7a24fe09dc7d51e4c581f64. The walkthrough and API reference use the same revision.

Source: examples/07-native-transports/src/native_demo/ports.cljs

View this exact file on GitHub.

(ns native-demo.ports
  (:require [cljs.core :refer [await]]
            [fast-twitch.client.core :as client])
  (:refer-global :only [Promise console]))

(defn ^:async -main
  []
  (let [channel (atom nil)
        received (Promise. (fn [resolve _]
                             (reset! channel (client/message-channel!
                                               {:codec :json
                                                :on-event #(resolve (:data %))}))))]
    (try (client/send! (:port1 @channel) {"values" [false nil 42]})
         (assert (= {"values" [false nil 42]} (await received)))
         (.log console "MessageChannel with an explicit JSON codec passed")
         (finally (client/close! (:port1 @channel)) (client/close! (:port2 @channel))))))

(set! *main-cli-fn* -main)

Source: examples/07-native-transports/deps.edn

View this exact file on GitHub.

{:aliases {:build {:main-opts ["-m" "native-demo.build"]}}
 :deps {fast-twitch/fast-twitch {:local/root "../.."}
        org.clojure/clojurescript {:git/sha "56a94ac13bfac22108e4d868dfd4763edaceb864"
                                   :git/url "https://github.com/clojure/clojurescript"}}
 :paths ["src" "dev"]}

Source: examples/07-native-transports/dev/native_demo/build.clj

View this exact file on GitHub.

(ns native-demo.build
  (:require [cljs.build.api :as cljs]))

(def modes
  #{"http" "websocket" "sse" "streams" "ports" "tcp-node" "tcp-deno" "tcp-bun"})

(defn -main
  [mode]
  (doseq [mode (if (= mode "all") (sort modes) [mode])]
    (when-not (modes mode) (throw (ex-info "Choose an example" {:modes modes})))
    (cljs/build "src"
                {:main (symbol (str "native-demo." mode))
                 :target :nodejs
                 :output-to (str "target/" mode ".cjs")
                 :output-dir (str "target/" mode)
                 :optimizations :simple})
    (println mode "COMPILED")))
Source revision a4eb73f96836d034c7a24fe09dc7d51e4c581f64

Built with Fast-Twitch · Integrant · Datastar

Search documentation

Search pages and API symbols

Start hereWelcome to Fast-TwitchRing HTTP applications and configured native clients and transports in ClojureScript.Start hereGetting startedCompile and run your first Fast-Twitch server.Core conceptsRequest & responseUnderstand the maps at the center of a Fast-Twitch application.Core conceptsRoutingMatch URL patterns and compose handlers.Core conceptsMiddlewareWrap handlers with focused request and response behavior.GuidesHTML & IntegrantCompose a UI system with Integrant and render Hiccup.