Hey,
Im currently porting an api crate from making blocking web requests to async.
There are instances where api endpoints return a list of other api endpoints for the user to call.
Up till now, this was implemented as a struct with a custom IntoIter implementation where calling next() made the web request.
Moving to async, i would prefer to keep the ability to represent this list of api endpoints in a way that can still be used with map/filter/collect etc.
To that end, i found Streams as well as FuturesUnordered and im unsure which one i should use, given that they both seem to serve a similar purpose (at least here)
Ideally, I would like it to be trivial to collect/map/filter the futures concurrently (not neccessarily in parallell, i.e. there should be multiple web requests waiting at the same time, but they need not neccessarily be compleated in parallel) if that helps narrowing it down.
for reference, this is the code i already tried with streams, and it seems to work, although it seems to only drive 1 future at a time.
struct ListIter<T> {...}
impl<T: Send + Sync + Unpin> ListIter<T> {
#[async_recursion]
async fn stream_next(&mut self) -> Option<crate::Result<T>> {
...
}
pub fn into_stream(self) -> impl Stream<Item = crate::Result<T>> + Unpin {
Box::pin(stream::unfold(self, |mut state| async move {
let item = state.stream_next().await;
item.map(|val| (val, state))
}))
}
}
...
let cards: Vec<Card> = query
.search()
.await?
.into_stream()
.filter_map(|card| future::ready(card.ok()) })
.filter(|card| {
future::ready(
card.prices.usd.is_some() || (!card.nonfoil && card.prices.usd_foil.is_some()),
)
})
.collect()
.await;