2013-04-05 33 views
13

Tôi biết rằng vấn đề của tôi có vẻ hơi phức tạp một chút. Nhưng tôi sẽ cố gắng thể hiện bản thân mình tốt.Làm cách nào để đợi các tác vụ không đồng bộ hoàn thành trong scala?

Tôi có phương pháp này mà tôi muốn trả lại một số Map[String, List[String]] chứa đầy dữ liệu.

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 
} 
} 

Mã của tôi có thể không được viết bằng cú pháp tối ưu.

Nhưng những gì tôi muốn là trả về kết quả nàyBản đồ với dữ liệu. Vấn đề của tôi là vì "get to facebook url" được thực hiện không đồng bộ, kết quả nàyMap được trả về trống. Tôi không muốn điều này trở nên trống rỗng.

Mã này trong phương pháp của tôi là giải pháp của tôi cho đến nay. Nó không hoạt động, rõ ràng, nhưng tôi hy vọng bạn có thể thấy những gì tôi đang cố gắng làm. Cảm thấy tự do để trả lời với suy nghĩ của bạn mặc dù bạn không chắc chắn, nó có thể đưa tôi đi đúng hướng.

+0

cách bạn có thể nối thêm giá trị vào dataList nếu đó là val? –

Trả lời

25

Sử dụng 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. 
    }; 
}; 

Một cách khác là để Await kết quả. (đây là hành động chặn).

Được sử dụng khi bạn cần phải trả lại kết quả

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); 
}; 

Hãy cẩn thận để thực hiện chặn Futures trong thi hành di chúc của mình, nếu không bạn kết thúc chặn tính toán song song khác. Điều này đặc biệt hữu ích đối với các yêu cầu S2S và RPC, trong đó việc chặn đôi khi không thể tránh được.

+0

Cảm ơn câu trả lời của bạn đã giúp :) Mặc dù giải pháp của tôi làm việc đó là sử dụng trả về 'Lời hứa [Chuỗi, Danh sách [String]]]' và khi tôi gọi nó, tôi đã kiểm tra tương lai hứa hẹn. Và trên onSuccess của tương lai, tôi đã làm một cái gì đó. Có lẽ tôi nên đăng giải pháp của mình. Nếu vậy hãy cho tôi biết. – raxelsson

+4

vui lòng đăng giải pháp của bạn, tôi quan tâm –

+0

@flavian cảm ơn bạn –

Các vấn đề liên quan