如何在Scala Play中管理状态!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)
}  

聊天室。join返回一个scala.concurrent.Future[(Iteratee[JsValue,_],Enumerator[JsValue])]。但是在Play!中使用的迭代器和枚举器在哪里?框架?WebSocket类(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
}

How does Play!当迭代器消耗输入时,管理它不断变化的状态?

值得注意的是,WebSocket本身只是一个哑容器。在play.core.server.netty中,魔法发生在不同的类中。

要理解这个魔力是什么,看一下f (WebSocket包含的函数)的签名是有指导意义的:

RequestHeader => (Enumerator[A], Iteratee[A, Unit]) => Unit

这是一个获取RequestHeaderEnumeratorIteratee的函数,并对它们进行处理。

因此,在未来的某个时刻,框架将为我们的WebSocket提供RequestHeader(应该是不言自明的),Enumerator[A](枚举器是源,在这种情况下,这些是从客户端接收的消息)和Iteratee[A, Unit](迭代器是接收器,在这种情况下,这是我们发送消息返回客户端的地方)。

WebSocket.adapter的情况下,WebSocket将通过EnumerateeEnumerator连接到Iteratee。在WebSocket.using的情况下,WebSocket将远程Enumerator连接到本地Iteratee,并将移除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
    }
  }

请注意,这段代码几乎肯定存在线程安全问题——在Scala中,您应该尽可能避免可变状态,或者使用actor或类似的方法。

或者,尝试WebSocket.using,并查看pushee Enumerator,与foreach Iteratee结合使用,尽管它有点麻烦。也许可以理解,推式枚举器在Play 2.1中被弃用了,因为它被新的通道系统所取代。

相关内容

  • 没有找到相关文章

最新更新