Mar*_*ark 4 scala enumerator websocket iterate playframework-2.0
我正在查看https://github.com/playframework/Play20/tree/master/samples/scala/websocket-chat上的示例
要制作一个websocket控制器,你可以这样写:
def chat(username: String) = WebSocket.async[JsValue] { request =>
ChatRoom.join(username)
}
Run Code Online (Sandbox Code Playgroud)
Chatroom.join返回一个scala.concurrent.Future [(Iteratee [JsValue,_],Enumerator [JsValue])].但是在Play中使用的iteratee和枚举器在哪里!框架?该网页套接字类(WebSocket.scala)似乎忽视了投入:
case class WebSocket[A](f: RequestHeader => (Enumerator[A], Iteratee[A, Unit]) => Unit) (implicit val frameFormatter: WebSocket.FrameFormatter[A]) extends Handler {
type FRAMES_TYPE = A
/**
* Returns itself, for better support in the routes file.
*
* @return itself
*/
def apply() = this
}
Run Code Online (Sandbox Code Playgroud)
怎么玩!在消耗输入时管理iteratee的变化状态?
值得注意的是,它WebSocket本身只是一个愚蠢的容器.魔术发生在各种类中play.core.server.netty.
要理解这个魔法是什么,查看f的签名是有益的(WebSocket包含的函数:
RequestHeader => (Enumerator[A], Iteratee[A, Unit]) => Unit
Run Code Online (Sandbox Code Playgroud)
这是一个带a RequestHeader,an Enumerator和an 的函数Iteratee,并用它们做一些事情.
因此,在未来的某个时刻,框架将为我们WebSocket提供一个RequestHeader(应该是自我解释的),一个Enumerator[A](枚举器是来源,在这种情况下,这些是从客户端接收的消息),并且Iteratee[A, Unit](Iteratees是接收器,在这种情况下,这是我们发送消息返回客户端的地方).
在这种情况下WebSocket.adapter,WebSocket将连接Enumerator到Iterateevia Enumeratee.在这种情况下WebSocket.using,WebSocket将远程连接Enumerator到本地Iteratee,并将remove连接Iteratee到本地Enumerator.
不是直接定义WebSocket,而是使用WebSocket对象中的一种便捷方法可能更容易.以下代码将回显之前收到的消息:
def mySocket = WebSocket.adapter {implicit req =>
var lastMessage = "No previous message"
Enumeratee.map[String] {msg =>
val response = lastMessage
lastMessage = msg
response
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,此代码几乎肯定存在线程安全问题 - 在Scala中,您应该尽可能避免使用可变状态,或者如果没有则使用actor或类似代码.
或者,尝试WebSocket.using,看看pushee Enumerator,与foreach一起Iteratee,虽然它是一个小小的提琴手.也许可以理解,pushee枚举器在Play 2.1中被弃用,因为它被新的频道系统所取代.
| 归档时间: |
|
| 查看次数: |
1087 次 |
| 最近记录: |