Reputation: 1089
I have a function to get a seq of workItemIds given JobIds, with following signature -
def getWorkItemIds(jobId: JobId): Future[Seq[WorkItemId]]
I have another function which given a WorkItemId would return a workItem. with signature -
def getWorkItem(workItemId: WorkItemId): Future[Option[WorkItem]]
Now I am trying to write a function which uses these two to return a seq of WorkItem given a JobId, like this -
def getWorkItemsForJob(jobId: JobId): Future[Seq[Future[Option[WorkItem]]]] = {
val workItemIds: Future[Seq[WorkItemId]] = getWorkItemIds(jobId)
val res = workItemIds.map {
idSeq => idSeq.map {
id => getWorkItem(id)
}
}
res
}
The problem is the return type, I don't want to return this monstrous type, instead something simpler like a Future[Seq[WorkItem]]
should be returned. Now I can flatten it like -
def getWorkItemsForJob(jobId: JobId): Future[Seq[WorkItem]] = {
val workItemIds: Future[Seq[WorkItemId]] = getWorkItemIds(jobId)
val res = workItemIds.map {
idSeq => idSeq.flatMap {
id => getWorkItem(id).get
}
}
res
}
which gives me the correct Future[Seq[WorkItem]]
type that I want, but it requires me to do a get on the future, which does not feel correct. I can also use await but that would be a blocking call. Is there anyway to flatten the above type without blocking ?
Upvotes: 1
Views: 94
Reputation: 8866
You can do it the following way:
def getWorkItemsForJob(jobId: JobId): Future[Seq[WorkItem]] =
for (
seq <- getWorkItemIds(jobId);
list <- Future.traverse(seq)(getWorkItem)
) yield list.flatten
Upvotes: 3
Reputation: 15074
What you are looking for is Future.traverse
:
def getWorkItemsForJob(jobId: JobId): Future[Seq[WorkItem]] =
getWorkItemIds(jobId).flatMap(Future.traverse(_)(getWorkItem).map(_.flatten))
The .traverse
call takes the Seq
from the getWorkItemIds
call and returns a Future[Seq]
of the results of calling getWorkItem
on each entry, without the inner Future
wrapping.
The .map(_.flatten)
near the end flattens out this inner Seq[Option[WorkItem]]
to just Seq[WorkItem]
.
Upvotes: 3