我试图了解Play 2.0框架的反应性I /O概念。为了从一开始就更好地理解,我决定跳过框架的助手来构造不同种类的迭代器,并Iteratee从头开始编写一个自定义,以供aBodyParser解析请求正文使用。
从Iteratees和ScalaBodyParser文档中的可用信息以及关于播放反应式I / O的两个演示开始,这就是我想出的:
import play.api.mvc._
import play.api.mvc.Results._
import play.api.libs.iteratee.{Iteratee, Input}
import play.api.libs.concurrent.Promise
import play.api.libs.iteratee.Input.{El, EOF, Empty}
01 object Upload extends Controller {
02 def send = Action(BodyParser(rh => new SomeIteratee)) { request =>
03 Ok("Done")
04 }
05 }
06
07 case class SomeIteratee(state: Symbol = 'Cont, input: Input[Array[Byte]] = Empty, received: Int = 0) extends Iteratee[Array[Byte], Either[Result, Int]] {
08 println(state + " " + input + " " + received)
09
10 def fold[B](
11 done: (Either[Result, Int], Input[Array[Byte]]) => Promise[B],
12 cont: (Input[Array[Byte]] => Iteratee[Array[Byte], Either[Result, Int]]) => Promise[B],
13 error: (String, Input[Array[Byte]]) => Promise[B]
14 ): Promise[B] = state match {
15 case 'Done => { println("Done"); done(Right(received), Input.Empty) }
16 case 'Cont => cont(in => in match {
17 case in: El[Array[Byte]] => copy(input = in, received = received + in.e.length)
18 case Empty => copy(input = in)
19 case EOF => copy(state = 'Done, input = in)
20 case _ => copy(state = 'Error, input = in)
21 })
22 case _ => { println("Error"); error("Some error.", input) }
23 }
24 }
(备注:所有这些东西对我来说都是新事物,因此,如果这完全是废话,请原谅。)Iteratee非常愚蠢,它只读取所有块,对接收到的字节数求和并打印一些消息。当我用一些数据调用控制器动作时,一切都会按预期进行-我可以观察到Iteratee接收到所有块,并且在读取所有数据时,它将切换为完成状态,请求结束。
现在,我开始研究代码,因为我想看看这两种情况的行为:
17 case in: El[Array[Byte]] => copy(state = if(received + in.e.length > 10000) 'Error else 'Cont, input = in, received = received + in.e.length)
所以我只是添加了一个条件,如果接收到超过10000个字节,则会切换到错误状态。我得到的输出是这样的:
'Cont Empty 0
'Cont El([B@38ecece6) 8192
'Error El([B@4ab50d3c) 16384
Error
Error
Error
Error
Error
Error
Error
Error
Error
Error
Error
然后,请求将永远挂起并且永远不会结束。我对上述文档的期望是,当我error在foldIteratee中调用函数时,应停止处理。这里发生的是,Iteratee的fold方法在error被调用之后被多次调用-好,然后请求挂起。
当我在读取所有输入之前切换到完成状态时,其行为非常相似。将第15行更改为:
15 case 'Done => { println("Done with " + input); done(if (input == EOF) Right(received) else Left(BadRequest), Input.Empty) }
第17行:
17 case in: El[Array[Byte]] => copy(state = if(received + in.e.length > 10000) 'Done else 'Cont, input = in, received = received + in.e.length)
产生以下输出:
'Cont Empty 0
'Cont El([B@16ce00a8) 8192
'Done El([B@2e8d214a) 16384
Done with El([B@2e8d214a)
Done with El([B@2e8d214a)
Done with El([B@2e8d214a)
Done with El([B@2e8d214a)
然后请求将永远挂起。
我的主要问题是为什么在上述情况下该请求被挂起。如果有人可以阐明这一点,我将不胜感激!
您的理解是完全正确的,我已将修复方法推向高手:
https://github.com/playframework/Play20/commit/ef70e641d9114ff8225332bf18b4dd995bd39bcc
修复了Iteratees中的两种情况以及例外情况。
在案例类中很好地使用副本来进行Iteratee BTW。
下一个过程很容易理解和复制,但会导致一个错误: activityA在其
从RunAction的完成处理程序调用SCNAction似乎会挂起SceneKit。 触摸事件或旋转设备似乎可以解除挂起的障碍。 繁殖: 1)采取默认的SceneKit项目,你得到的启动与旋转的宇宙飞船。 2) 替换动画代码: 与: 3)在模拟器或真实设备上运行(两者问题相同) 4)结果是: > 宇宙飞船旋转正常 DONE ROTATE打印出来了OK 现在它挂起来了 轻触屏幕(或将设备旋转至横向)
问题内容: 将以下内容放入文件 hello.py中 (如果还没有的话): 适当填写第一行。 现在输入 您会看到一些ls输出。 现在输入 然后从解释器类型中 和瞧!挂了!如果将代码包装在一个函数中,而是执行此操作,它将解开。 在模块初始化中使用Paramiko时为什么会挂起? Paramiko甚至如何知道它最初是在模块初始化期间使用的? 问题答案: Paramiko使用单独的线程进行基础传输。您 永
问题内容: 我正在尝试与大学的MySQL数据库建立连接,但该连接已挂起。 此调用:打印(在我最终杀死它之后): 我刚刚从下载的MySQL连接器/ J 这里。我不确定这是否是问题的一部分。我非常准确地遵循了指示。 我也可以像这样在命令行上连接到mysql: 可能的问题: 我写的Java代码 我如何安装MySQL Connector / J 某种网络问题阻止了连接 问题: 我应该怎么解决这个问题?为什
为什么虽然它没有得到 http.status === 200 但它没有警报失败!
在我的项目中有一个ViewController,它包含一些子视图(例如按钮)。它显示/隐藏这些按钮,总是带有动画。 它有一个这样的界面: 实现如下所示: 当被调用时,然后经过一段时间( 我尝试将“隐藏”持续时间更改为0.1,但没有帮助-在“隐藏(0.1)”“显示(0.2)”调用之后,“隐藏”回调在“显示”回调之后调用,我的按钮不可见。 我添加了一个快速修复方法,缓存visible参数,如果状态应该