Skip to content

Instantly share code, notes, and snippets.

@aziis98
Last active June 4, 2022 11:02
Show Gist options
  • Select an option

  • Save aziis98/62e972e8360aeb2b8dfbd8adfc9b0295 to your computer and use it in GitHub Desktop.

Select an option

Save aziis98/62e972e8360aeb2b8dfbd8adfc9b0295 to your computer and use it in GitHub Desktop.

Message Passing in JS

A simple function to handle a comunication over TCP via JSON using js generators.

Usage

Write a generator for each side of the conversation. To send or receive a message at some point just yield with one of the following functions

import { awaitMessage, sendMessage } from './mp.js'

function* () {
  ...
  yield sendMessage({ msg: 'hi', x: [1, 2, 3] })
  ... 
}
  
function* () {
  ...
  const { msg, x } = yield awaitMessage()
  ... 
}

TODO

  • Maybe some better names:

    sendMessage(obj) -> send(obj)

    awaitMessage() -> receive()

    runMessagePassing(socket, actorFn) -> spawn(socket, actorFn)

import { Socket } from 'net'
import { awaitMessage, runMessagePassing, sendMessage } from './mp.js'
function* clientHandler() {
console.log('Client sending message to server')
yield sendMessage('client says hi!')
const msg1 = yield awaitMessage()
console.log('Server:', msg1)
console.log('Client sending message to server')
yield sendMessage('client says goodbye!')
}
const client = new Socket()
client.connect(8080, 'localhost', () => {
console.log('Connected client to localhost:8080')
runMessagePassing(client, clientHandler)
})
import { Server } from 'net'
import { awaitMessage, runMessagePassing, sendMessage } from './mp.js'
function* serverHandler() {
const msg1 = yield awaitMessage()
console.log('Client:', msg1)
console.log('Server sending message to client')
yield sendMessage('server says hi!')
const msg2 = yield awaitMessage()
console.log('Client:', msg2)
}
const server = new Server(socket => {
console.log(`New client on localhost:8080`)
runMessagePassing(socket, serverHandler)
})
server.listen(8080, 'localhost', () => {
console.log('Started server on localhost:8080')
})
export function sendMessage(message) {
return { type: 'send', value: message }
}
export function awaitMessage() {
return { type: 'await' }
}
export function runMessagePassing(socket, handler) {
const queue = []
const it = handler()
let lastAction = null // null if ready to process next action
const advance = () => {
console.log('advance()')
if (lastAction === null) {
lastAction = it.next()
}
if (lastAction.done) {
console.log('done!')
return
}
const payload = lastAction.value
if (payload.type === 'send') {
process.stdout.write('Sending: ')
console.dir(lastAction, { depth: null })
// Handle "send" actions
socket.write(JSON.stringify(payload.value) + '\n')
lastAction = null
} else if (payload.type === 'await') {
if (queue.length === 0) {
return
}
const response = queue.pop()
lastAction = it.next(response)
} else {
throw 'Invalid action'
}
setTimeout(advance, 0)
}
// Handle "await" actions
socket.on('data', data => {
console.dir(data.toString(), { depth: null })
const response = JSON.parse(data.toString())
queue.push(response)
process.stdout.write('Received: ')
console.dir(response, { depth: null })
setTimeout(advance, 0)
})
setTimeout(advance, 0)
}
//
// Server
//
Started server on localhost:8080
New client on localhost:8080
advance()
'"client says hi!"\n'
Received: 'client says hi!'
advance()
Client: client says hi!
Server sending message to client
advance()
Sending: { value: { type: 'send', value: 'server says hi!' }, done: false }
advance()
'"client says goodbye!"\n'
Received: 'client says goodbye!'
advance()
Client: client says goodbye!
advance()
done!
//
// Client
//
Connected client to localhost:8080
advance()
Client sending message to server
Sending: { value: { type: 'send', value: 'client says hi!' }, done: false }
advance()
'"server says hi!"\n'
Received: 'server says hi!'
advance()
Server: server says hi!
Client sending message to server
advance()
Sending: { value: { type: 'send', value: 'client says goodbye!' }, done: false }
advance()
done!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment