Skip to content
Snippets Groups Projects
Commit d3dabc94 authored by Will Billingsley's avatar Will Billingsley
Browse files

Made one of the websocket examples more idiomatic

parent 70d8eeb1
Branches master
No related tags found
No related merge requests found
......@@ -87,7 +87,7 @@ class ExamplesController @Inject()(cc: ControllerComponents)(implicit ec: Execut
*
* @return
*/
def websocketWithHelper():WebSocket = {
def webSocketWithHelper():WebSocket = {
WebSocketHelper.createWebSocket[String, String](
{ queue =>
// We now have an asynchronous queue. What would we like to do with it
......@@ -109,39 +109,44 @@ class ExamplesController @Inject()(cc: ControllerComponents)(implicit ec: Execut
* asynchronous work. However, using this template, you should just
* @return
*/
def websocket() = WebSocket.accept[String, String] { request =>
// Our source is going to be an asynchronous queue we can push messages to with 'out.offer(msg)'. This is going to
// be the "source" of our flow. A complication is it doesn't create the queue immediately - this just says
// *when* this source is connected to a flow, create a queue. So we don't have a queue yet.
val outSource = Source.queue[String](50, OverflowStrategy.backpressure)
def webSocket() = WebSocket.accept[String, String] { request =>
// Because I want to refer to the queue in the sink, but I haven't actually got the queue yet, I'm just creating
// a box to put our queue in. At the moment, it's empty
var outOpt:Option[SourceQueueWithComplete[String]] = None
// Create a "sink" that describes what we want to do with each message. Here, I'm just going to count the characters
// and echo it straight back out on the "out" queue.
val in = Sink.foreach[String] { message =>
// A websocket is made from a "flow" - a source of messages up to the browser, and a sink for messages from the browser.
// We're going to need to give this function our Sink and our Source as arguments.
Flow.fromSinkAndSourceCoupledMat(
// If we have an out queue, send the message on it
outOpt foreach { out =>
out.offer(s"That message had ${message.length} characters in it")
}
// Create a "sink" that describes what we want to do with each message. Here, I'm just going to count the characters
// and echo it straight back out on the "out" queue.
Sink.foreach[String] { message =>
}
// If we have an out queue, send the message on it
outOpt foreach { out =>
out.offer(s"That message had ${message.length} characters in it")
}
},
// This defines a "flow" -- something that has an input and an output.
// "Coupled" means that if the input closes, the output will close
// "Mat" means "materialised" -- ie, it'll give us the output queue that gets created and the Future that will
// complete when the flow is done.
Flow.fromSinkAndSourceCoupledMat(in, outSource) { case (done, out) =>
// Our source is going to be an asynchronous queue we can push messages to with 'out.offer(msg)'.
// The queue will be created when the connection is complete - this just says what it *will* be
Source.queue[String](50, OverflowStrategy.backpressure)
// done is a future that will complete when the flow finishes
) { case (done, queue) =>
// the second argument list is a callback that takes a tuple with two arguments.
// done is a future (like a JavaScript promise) that will complete when the flow finishes
// out is our "materialised" output queue. All we need do is put it in the box we made earlier
out.offer("Connected!")
outOpt = Some(out)
// Send a connected message to the browser
queue.offer("Connected!")
// Put the queue in the box we defined earlier
outOpt = Some(queue)
// When the connection has ended, empty the box and println that it's closed
done.foreach { _ =>
outOpt = None
println("Connection closed!")
......@@ -149,6 +154,7 @@ class ExamplesController @Inject()(cc: ControllerComponents)(implicit ec: Execut
}
}
/**
......
......@@ -11,8 +11,8 @@ POST /example/json controllers.ExamplesController.receiveJsonPo
GET /example/game controllers.ExamplesController.game(id:Option[String])
GET /example/socket controllers.ExamplesController.websocket()
GET /example/time controllers.ExamplesController.websocketWithHelper()
GET /example/socket controllers.ExamplesController.webSocket()
GET /example/time controllers.ExamplesController.webSocketWithHelper()
GET /example/eventsource controllers.ExamplesController.eventSource()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment