使用scala.concurrent.Promise替换play.api.libs.concurrent.Promise时出错

时间:2013-09-25 03:15:08

标签: scala playframework playframework-2.0

我正在尝试从Play 2.1.3升级到2.2.0,并且在尝试编译时遇到错误。主要的变化是不推荐使用play.api.libs.concurrent.Promise,并指示用scala.concurrent.Promise替换它。编译错误如下:

错误讯息:

WebSocketJoin.scala:23: object creation impossible, since method fold in trait Iteratee of type [B](folder: play.api.libs.iteratee.Step[A,B] => scala.concurrent.Future[B])(implicit ec: scala.concurrent.ExecutionContext)scala.concurrent.Future[B] is not defined
[error]         def wrap(delegate: Iteratee[A, B]): Iteratee[A, B] = new Iteratee[A, B] {
[error]                                                                  ^
[error] one error found
[error] (adapter-api/compile:compile) Compilation failed

代码:

package utils

import play.api.libs.iteratee.{Step, Enumerator, Iteratee}
import scala.concurrent.{Promise, ExecutionContext, Future}
import ExecutionContext.Implicits.global

object WebSocketJoin {

  /**
   * Create a joined iteratee enumerator pair.
   *
   * When the enumerator is applied to an iteratee, the iteratee subsequently consumes whatever the iteratee in the pair
   * is applied to.  Consequently the enumerator is "one shot", applying it to subsequent iteratees will throw an
   * exception.
   */
  def joined[A]: (Iteratee[A, Unit], Enumerator[A]) = {
    val promisedIteratee = Promise[Iteratee[A, Unit]]()
    val enumerator = new Enumerator[A] {
      def apply[B](i: Iteratee[A, B]) = {
        val doneIteratee = Promise[Iteratee[A, B]]()

        // Equivalent to map, but allows us to handle failures
        def wrap(delegate: Iteratee[A, B]): Iteratee[A, B] = new Iteratee[A, B] {
          def fold[C](folder: (Step[A, B]) => Future[C]) = {
            val toReturn = delegate.fold {
              case done @ Step.Done(a, in) => {
                doneIteratee.success(done.it)
                folder(done)
              }
              case Step.Cont(k) => {
                folder(Step.Cont(k.andThen(wrap)))
              }
              case err => folder(err)
            }
            toReturn.onFailure {
              case e => doneIteratee.failure(e)
            }
            toReturn
          }
        }

        if (promisedIteratee.trySuccess(wrap(i).map(_ => ()))) {
          doneIteratee.future
        } else {
          throw new IllegalStateException("Joined enumerator may only be applied once")
        }
      }
    }
    (Iteratee.flatten(promisedIteratee.future), enumerator)
  }
}

1 个答案:

答案 0 :(得分:5)

我在博客文章中发布的已加入的iteratee / enumerator对现在在Play 2.2.0中以play.api.libs.iteratee.Concurrent.joined的形式提供。切换到该,您可以从代码库中删除上述代码。

要修改代码,请修改第24行的方法以接受隐式ExecutionContext。 Play 2.2更改了iteratee API,以便许多事情现在接受异常上下文:

def fold[C](folder: (Step[A, B]) => Future[C])(implicit ec: ExecutionContext)