2013-04-05 16 views
13

Sorunumun biraz karmaşık görünebileceğinin farkındayım. Ama kendimi iyi ifade etmeye çalışacağım.Senkronize tamamlamak için zaman uyumsuz görevler için nasıl beklerim?

Verilerle dolu bir Map[String, List[String]] dönmek istediğim bu yönteme sahibim.

def myFunction():Map[String, List[String]] = { 

    val userMap = Map[String, String](("123456", "ASDBYYBAYGS456789"), 
            ("54321", "HGFDSA5432")) 

    //the result map to return when all data is collected and added 
    val resultMap:Future[Map[String, List[String]]] 

    //when this map is finished (filled) this map is set to resultMap 
    val progressMap = Map[String, List[String]]() 

    for(user <- userMap){ 

    //facebook graph API call to get posts. 
    val responsePost = WS.url("async get to facebook url").get() 

    responsePosts.flatMap { response => 
     val jsonBody = response.json 
     val dataList = List[String]() 

     for(i <-0 until 5){ 

      //parse the json-data to strings 
      val messages = (jsonBody.\("statuses").\("data")(i).\("message")) 
      val likesArray = (jsonBody.\("statuses").\("data")(i).\\("data")).flatMap(_.as[List[JsObject]]) 
      val likes = likesArray.length 

      //Put post with likes in temporary list 
      dataList ::=  ("Post: " + message.toString + " Likes: " + likes.toString) 
     } 

      //facebook graph API call to get friends. 
      val responseFriends = WS.url("async get to facebook url").get() 

      responseFriends.map { response => 
       val jsonBody = response.json 
       val friendCount = jsonBody.\("data")(0).\("friend_count").toString 

       //add "Friends: xxx" to the dataList and add the new row to resultMap containig a list with post and friends. 
       dataList ::= ("Friends: " + friendCount) 
       progressMap += user._1 -> dataList 

       //check if all users has been updated 
       if(progressMap.size == userMap.size){ 
        resultMap = progressMap 
       } 
      } 
     } 
    } 

    //return the resultMap. 
    return resultMap 
} 
} 

Kodum en iyi sözdizimi ile yazılmamış olabilir.

Ama benim istediğim, bu sonucu döndürmek. Benim sorunum, "get to facebook url" eşzamansız olarak yapıldığından bu sonuç boş döndürülmüş olmasıdır. Bunun boş kalmasını istemiyorum.

Bu kod benim yöntemimde şu ana kadar benim çözümümdür. Açıkça çalışmıyor, ama umarım ne yapmaya çalıştığımı görebilirsiniz. Emin olmasan bile düşüncelerinle cevap vermekte özgürsün, beni doğru yola koyabilir.

+0

Değeri olan dataList'e değerleri nasıl eklersiniz? –

cevap

25

Kullanım scala.concurrent.{Future, Promise}:

def doAsyncAction: Promise[T] = { 
    val p = Promise[T] 
    p success doSomeOperation 
    p 
} 

def useResult = { 
    val async = doAsyncAction; 
    // The return of the below is Unit. 
    async.future onSuccess { 
     // do action. 
    }; 
}; 

bir başka yolu Await sonuç etmektir. (Bu bir engelleme eylemidir). Eğer bir sonuç

import scala.concurrent.{ ExecutionContext, ExecutionContext$, Future, Promise, Await } 
import scala.concurrent.duration._ 

def method: Option[T] = { 
    val future: Future[T] = Future { 
     someAction 
    } 
    val response = future map { 
     items => Some(items) 
    } recover { 
     case timeout: java.util.concurrent.TimeoutException => None 
    } 
    Await.result(future, 5000 millis); 
}; 

kendi yürütücü Futures engelleme yürütmek için dikkatli olun dönmek gerektiğinde kullanılır

, aksi takdirde diğer paralel hesaplama engelleme sonunda. Bu, engellemenin bazen önlenemediği S2S ve RPC istekleri için özellikle yararlıdır.

+0

Cevabınız için teşekkür ederim yardımcı oldu :) Çalışmamı sağlayan çözümüm bir “İade [Harita [Dize, Liste [Dize]]]' i kullanmaktı ve onu çağırdığımda promises'in geleceğini kontrol ettim. Ve bu geleceğin başarısı üzerine, bir şey yaptım. Belki de çözümümü yollamalıyım. Eğer öyleyse bana bildirin. – raxelsson

+4

lütfen çözümünüzü gönderin, ilgileniyorum –

+0

@flavian thank you –

İlgili konular