Extract Result from Tokio Runtime

Hello everybody,

I want to do a simple web request using the hyper create.

Defining the request as a Future is easy:

let client = Client::new();

let uri = "http://httpbin.org/ip".parse().unwrap();

client
    .get(uri)
    .map(|res| {
        println!("Response: {}", res.status());
    })
    .map_err(|err| {
        println!("Error: {}", err);
    })

This I can now lazily execute using the Tokio runtime:



fn main() {

// empty string
let response_body = "";

 rt::run(rt::lazy(|| {
    // code from above
}));

// get response body into `response_body`
}


What's the most ideomatic way to export a result from the tokio run-time?
Currently I thinking about a wrapper like this, but there must me something more straight forward:

fn rt_run_result<T, E, F>(future: F) -> Result<T, E>
    where
        F: Future<Item=T, Error=E> + Send + 'static,
        T: Send + Sync + 'static,
        E: Send + Sync + 'static,
{
    // There must be an easier way to do this...
    let result = Arc::new(Mutex::new(Option::None));
    let result_value = result.clone();
    let result_error = result.clone();
    rt::run(
        future
            .map(move |item| {
                let mut guard = result_value.lock().unwrap();
                *guard = Option::Some(Ok(item))
            })
            .map_err(move |error| {
                let mut guard = result_error.lock().unwrap();
                *guard = Option::Some(Err(error))
            }),
    );
    let mut guard = result.lock().unwrap();
    guard.take().unwrap()
}

Thanks,
Stefan

It depends how you want to receive it. Of course, it's suboptimal to cross between futures and sync code but sometimes it's necessary.

In general: If you want to stash the result in some known variable I don't think you can avoid using a Mutex or RwLock. Another option that can work well is a regular mpsc channel - you have the flexibility whether to block or poll, and you can easily clone the sending end for use in multiple combinators.

In this specific case: If you just want to block until some futures-based code finishes, instead of spawning it on the runtime you could perhaps call wait() on the future returned created by your get() chain.

Edit: By the way, it's not necessary to split out map and map_err - you can use then to get a Result in the one handler instead.