flatMap
và map
là bạn của bạn! Hai phương pháp này của loại Promise
cho phép chuyển đổi kết quả của một Promise[A]
thành một số khác Promise[B]
.
Đây là một ví dụ đơn giản của họ trong chiến tranh (tôi cố tình viết một cách rõ ràng hơn chú thích loại hơn cần thiết, chỉ để giúp đỡ để hiểu nơi biến đổi xảy ra):
def preferredSongsAndArtist = Action {
// Fetch the list of your preferred songs from Web Service “A”
val songsP: Promise[Response] = WS.url(WS_A).get
val resultP: Promise[List[Something]] = songsP.flatMap { respA =>
val songs: List[Song] = Json.fromJson(respA.json)
// Then, for each song, fetch the artist detail from Web Service “B”
val result: List[Promise[Something]] = songs.map { song =>
val artistP = WS.url(WS_B(song)).get
artistP.map { respB =>
val artist: Artist = Json.fromJson(respB.json)
// Then, generate and return something using the song and artist
val something: Something = generate(song, artist)
something
}
}
Promise.sequence(result) // Transform the List[Promise[Something]] into a Promise[List[Something]]
}
// Then return the result
Async {
resultP.map { things: List[Something] =>
Ok(Json.toJson(things))
}
}
}
Nếu không có chú thích loại không cần thiết và sử dụng “ để hiểu ”, bạn có thể viết mã biểu cảm sau đây:
def preferredSongsAndArtist = Action {
Async {
for {
// Fetch the list of your preferred songs from Web Service “A”
respA <- WS.url(WS_A).get
songs = Json.fromJson[List[Song]](respA.json)
// Then, for each song, fetch the artist detail from Web Service “B”
result <- Promise.sequence(songs.map { song =>
for {
respB <- WS.url(WS_B(song)).get
artist = Json.fromJson[Artist](respB.json)
} yield {
// Then, generate and return something using the song and artist
generate(song, artist)
}
})
// Then return the result
} yield {
Ok(Json.toJson(result))
}
}
}
Nguồn
2012-04-03 13:11:06
Cảm ơn câu trả lời của bạn. Tôi phân tích và kiểm tra giải pháp này càng sớm càng tốt. – YoT
@julien Điều gì sẽ xảy ra nếu bất kỳ dịch vụ web nào hết thời gian chờ hoặc trả lại 500? getOrElse? –
Lời hứa sẽ được đổi bằng giá trị [Thrown] (http://www.playframework.org/documentation/api/2.0/scala/play/api/libs/concurrent/Thrown.html). Bạn có thể xử lý trường hợp này bằng cách sử dụng [mở rộng] (http://www.playframework.org/documentation/api/2.0/scala/index.html#play.api.libs.concurrent.Promise) chẳng hạn. –