1

私のコントローラーには、一連のSmsオブジェクトがあるとしましょう。これらのオブジェクトのそれぞれについて、Web サービスを呼び出したいと思います。その後、すべての呼び出しが成功すると、表示する SMS オブジェクトが返されます。

コントローラ:

def inviteBySms() = Action {
    implicit request => {
      val smsSet = getSet()
      Async {
        smsSet.map(sms => callSmsService(sms).map(response => {
          response.status match {
            case 200 => {
              // somehow add the sms object to a success set  
            }
            case _ => {
              // ignore
            }
          }
        }))
      // Return Ok() with the success Set[SMS]
      }
    } 

}

コントローラーのメソッド:

def postToService(sms: Sms) = {

    val params = Map(Seq(current.configuration.getString("sms.service.user").getOrElse("")),
          "pass" -> Seq(current.configuration.getString("sms.service.password").getOrElse("")),
          "mobilephone" -> Seq(sms.number))
        )


    val futureResponse = WS.url(Play.current.configuration
          .getString("sms.service.url").getOrElse(""))
          .withHeaders("Content-Type" -> "application/x-www-form-urlencoded; charset=utf-8")
          .post(params)
}
4

2 に答える 2

1

さらなる議論の後、これが私の最初の試みよりも最も正しい答えです。

私のコードでは、Sms を as として定義しtype Sms = String、WS.url().get を直接呼び出しています。

まず、callSmsService(sms: Sms)はサービスを呼び出して を返さないようにする必要がありますが、戻り値が 200 であるかどうかに応じてResponse、すでにそれを返しています。アイデアは、元のインスタンスmap()を返すか、後でそれらを集約できるようにすることです:SmsNone

def callSmsService(sms: Sms): Future[Option[Sms]] = {
  WS.url(sms).get
    .map { 
      response => if (response.status == 200) Some(sms) else None
    }
}

map()この関数を使用して、最初の Sms を設定できるようになりました。

val futureOptionSet: Set[Future[Option[Sms]]] = smsSet.map { sms => callSmsService(sms) }

次に、 をSet[Future]グローバルに変換する必要があります ( asked byFuture[Set]を構築するには、一意の Future が必要です)。Future[Result]Async{...}

val optionSetFuture: Future[Set[Option[Sms]]] = Future.sequence(futureOptionSet)

これで、グローバルな未来をマッピングして、成功した SMS のみを収集できます

val smsSetFuture: Future[Set[Sms]] = optionSetFuture.map { set => set.collect { case Some(sms) => sms }}

この最後の を使用すると、 a をFuture実行して amap()を構築できます。Future[Response]

smsSetFuture.map( successfulSmsSet: Set[Sms] => {
  // do something with successfulSmsSet
  ok(...) 
})

明示的な戻り値の型を段階的に詳しく説明しましたが、もちろん、中間値と明示的な型なしでいくつかの手順を組み合わせることができます。

于 2013-05-24T19:01:29.243 に答える
0

まず、次のように呼び出します。

smsSet.map(sms => callSmsService(sms))

Set[Future[Response]] を取得し、それを Future.sequence でラップして Future[Set[Response]] を取得するには:

Future.sequence(smsSet.map(sms => callSmsService(sms)))

そして、Future[Set[Response]] では、filter() と map() で Future[Set[SMS]] を取得できます。

val futureSetSms = Future.sequence(smsSet.map(sms => callSmsService(sms)))
   .filter{_.status == 200}
   .map(response => {...construct your SMS...})

次に、それを Async{} で使用できる Future[Result] にマップする必要があります。

futureSetSms.map { smsSet => Ok(...) }
于 2013-05-24T14:14:49.513 に答える