Skip to content

Instantly share code, notes, and snippets.

@zeusdeux
Last active March 7, 2018 03:39
Show Gist options
  • Save zeusdeux/c56359801313f30d50b1952bfad26182 to your computer and use it in GitHub Desktop.
Save zeusdeux/c56359801313f30d50b1952bfad26182 to your computer and use it in GitHub Desktop.
Async generators as wrappers around event emitters
let socket = new WebSocket('wss://echo.websocket.org')
async function main(socket) {
for await (let {value, done} of getDataFromWebSocket(socket)) {
if (!done) console.log('Data:', value)
else console.log('WebSocket is closed.')
}
return 'Done running the main fn!'
} // hit return/enter
// if you're running this in the dev console run this first and hit return/enter
await main(socket)
// since we are using the demo hosted echo websocket, it echoes what we send it
// so to receive a value, we first send it a value
// select all upto socket.send(4) and hit enter and you'll see the Data: <number>
// as ouput
socket.send(1)
socket.send(2)
socket.send(3)
socket.send(4)
// after seeing the output of the send commands type this and hit enter
// you'll see WebSocket is closed. printed followed by the promise
// return by the async main() fn resolving to the return value of
// main which is 'Done running the main fn!'
// This tells us that the loop in main was exited and main returned as well
socket.close()
async function* getDataFromWebSocket(sock) {
// from https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Ready_state_constants
const READY_STATE_MAP = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']
// our custom data object that the promise for a websocket message resolves to
// it has value with raw event data and a done property which is set to true
// when the WebSocket connection has been closed
const makeDataObj = evt => ({
value: evt.data,
done: READY_STATE_MAP[evt.target.readyState] === 'CLOSED'
})
// hoisted out promise along with the resolve and reject fns for that promise
let prom, resolve, reject
// true iff the WebSocket connection has been closed
let done = false
sock.onmessage = e => resolve(makeDataObj(e))
sock.onclose = e => {
done = true
resolve(makeDataObj(e))
}
while (!done) {
prom = new Promise((res, rej) => {
resolve = res
reject = rej
})
yield prom
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment