scala – 为什么调用错误或在BodyParser的Iteratee中完成请求在P
我试图了解Play 2.0框架的反应I / O概念.为了从一开始就更好地理解,我决定跳过框架的助手来构造不同种类的迭代,并从头开始编写一个自定义Iteratee,供BodyParser用来解析请求体.
从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],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 } (备注:所有这些对我来说都是新的,所以请原谅,如果有关于此的话就是全部废话.) 现在我开始使用代码了,因为我想看看这两种情况的行为: >在读取所有输入之前切换到状态错误. 我对上述文档的理解是两者都应该是可能的,但实际上我无法理解观察到的行为.为了测试第一种情况,我将上面代码的第17行更改为: 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 然后请求永远挂起,永远不会结束.我对上述文档的期望是,当我在Iteratee的fold中调用error函数时,应该停止处理.这里发生的事情是,在调用错误后多次调用Iteratee的fold方法 – 然后请求挂起. 当我在读取所有输入之前切换到完成状态时,行为非常相似.将第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,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. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |