PFA hard
PFA hard

Reputation: 91

Rust tokio alternative to fold and map to run a function concurrently with different inputs

I need a way to run the same function many times with different inputs. And since the function depends on a slow web API, I need to run it concurrently and collect the results in one variable. I use the following:

    use tokio_stream::StreamExt;
    async fn run(input: &str) -> Vec<String> {
        vec![String::from(input), String::from(input)]
    }


    async fn main() {
        let mut input = tokio_stream::iter(vec!["1","2","3","4","5","6","7","8"]);
        let mut handles = vec![];
        
        
        while let Some(domain) = input.next().await {
            handles.push(run(domain));
        }
        
        let mut results = vec![];
        let mut handles = tokio_stream::iter(handles);
        while let Some(handle) = handles.next().await {
            results.extend(handle.await);
        }
    }

I know there is a way with the futures crate, but I don't know if I can use it with tokio. Also tokio_stream::StreamExt contains fold and map methods but I can't find a way to use them without calling await. What is the best way to do this?

Upvotes: 0

Views: 3197

Answers (1)

Jmb
Jmb

Reputation: 23463

IIUC what you want, you can use tokio::spawn to launch your tasks in the background and futures::join_all to wait until they have all completed. E.g. something like this (untested):

async fn run(input: &str) -> Vec<String> {
    vec![String::from(input), String::from(input)]
}

async fn main() {
    let input = vec!["1","2","3","4","5","6","7","8"];

    let handles = input.iter().map (|domain| {
        tokio::spawn (async move { run (domain).await })
    });

    let results = futures::join_all (handles).await;
}

Upvotes: 2

Related Questions