Reference · Channels

channel.on

signature
channel.on(str, fn, map | null=) -> null

What it does

Handles a channel on the server: written at the top of a program, once for a name, it makes f(msg, peer) the function that gets each message a page sends on that channel. peer is { id, session }: twelve hex characters made for the page's connection, and the page's session as it was when it connected. The options map takes join(peer), which decides whether a page may join (anything but null, false or an error says yes), leave(peer), which hears that a page left, and tenants. Each of the three functions is called with as many arguments as it declares. Each tenant has its own room of a channel (since 0.7: one room for all): pages on acme.example.com and evil.example.com joining lobby are in two rooms, and tenants: "shared" makes one room for every tenant. The program then serves: a plain program with channel.on in it does not end.

Examples

in a program
channel.on("game", (msg, peer) => {    // Everyone else in the channel sees the move.    channel.broadcast("game", { id: peer.id, pos: msg.pos }, { except: peer })})channel.on("chat", (msg, peer) => {    db.exec("insert into messages (who, text) values (?, ?)", peer.session.user, msg.text)    channel.broadcast("chat", { who: peer.session.user, text: msg.text })}, {    join: (peer) => peer.session.user != null,    leave: (peer) => channel.broadcast("chat", { left: peer.id }),})

The other side of "chat" is a page whose component opens the channel with channel.open: its send reaches the handler above, and each broadcast reaches its function. The join lets in only a signed-in visitor, so the page is for them:

in a program
component Chat() {    state lines = []    state draft = ""    let chat = channel.open("chat", (m) => { lines = m.left != null ? lines : lines + [m] })    <form @submit={() => { chat.send({ text: draft }); draft = "" }}>        <ul>{for l in lines => <li><b>{l.who}</b> {l.text}</li>}</ul>        <input value={draft}/>    </form>}route GET /chat = session().user == null ? redirect("/login") : <html><body><Chat/></body></html>

A page turned away by join says so in its console: quillo: the server did not let this page join channel chat. See Real time for the whole program.

Edge cases

in a program
channel.on("room:7.lobby", (msg, peer) => channel.send("room:7.lobby", peer, { echo: msg }))channel.on("ticks", (msg) => print(msg))        // f declared with one parameter gets onechannel.on("news", (msg) => msg, { tenants: "shared" })   // one room for every tenant

Errors

A bad name, a second argument that is not a function, a join or leave that is not one, a tenants other than "shared" or "own", an option that does not exist, and a name handled twice are runtime errors when the program starts, so the program does not serve. There are no error values.

this one fails
channel.on("bad name!", (msg) => msg)
output
line 1: `channel.on`: a channel's name is letters, digits, `_`, `-`, `.` and `:`, up to 64, got "bad name!"
this one fails
channel.on("game", (msg) => msg)channel.on("game", (msg) => msg)
output
line 2: `channel.on`: the program already handles channel "game"
this one fails
channel.on("game", (msg) => msg, { join: true })
output
line 1: `channel.on`: `join` is a function of the page
this one fails
channel.on("game", (msg) => msg, { tenant: "shared" })
output
line 1: `channel.on` has no option `tenant` (it takes join, leave and tenants)
this one fails
channel.on("game", (msg) => msg, { tenants: true })
output
line 1: `channel.on`: `tenants` is "shared" (one room for every tenant) or "own", got true

Chaining

channel.on gives null and is not piped. Inside f, the other channel functions answer: channel.send to the page that wrote, channel.broadcast to all, and channel.peers to see who is there.

in a program
channel.on("poll", (msg, peer) => {    let n = channel.peers("poll") | len    channel.send("poll", peer, { you_and: n - 1, others: n - 1 })})

See also

channel.open, channel.send, channel.broadcast, channel.peers, session, udp.listen

Thread
5Useful? Like it, or add to its thread below.

Thread 0 posts

On channel.on(): questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.

    Edit this page on GitHub · every example's output was made by running it (tools/refcheck.mjs) · questions on Discord or r/quillo