What is the difference between `then`, `and_then` and `or_else` in Rust futures?

不羁岁月 提交于 2019-12-24 05:34:06

问题


I am learning to use Rust futures and I am finding it extremely confusing. I feel like I am being stupid but when would then, and_then and or_else be used? What return types are expected?

Please provide some examples of the different situations you would expect to see them.


回答1:


TL;DR: then is used when you want to do something regardless of if the future was successful or not, and_then runs the closure only when the future succeeded, and or_else runs the closure only when the future failed.

and_then and or_else are direct analogs to the methods of the same name on Result .


Your first step should be to read the docs. The documentation contains the exact method signatures (which explain what types it expects and what the return types are), prose describing each method, and example usage as well.

I've extracted small snippets of the docs and emphasized the relevant parts.

Future::then:

This function can be used to ensure a computation runs regardless of the conclusion of the future. The closure provided will be yielded a Result once the future is complete.

The returned value of the closure must implement the IntoFuture trait and can represent some more work to be done before the composed future is finished.

Future::and_then:

This function can be used to chain two futures together and ensure that the final future isn't resolved until both have finished. The closure provided is yielded the successful result of this future and returns another value which can be converted into a future.

Future::or_else

Return a future that passes along this future's value if it succeeds, and otherwise passes the error to the closure f and waits for the future it returns.

The return type for all three methods is any type that can be converted into another future.

  • then: no additional restrictions on the return type.
  • and_then requires that the error type of the returned future match the starting future's error type.
  • or_else requires that the success type of the returned future match the starting future's success type.

use futures::{future, Future}; // 0.1.25

struct Error;

fn download_from_server(server: u8) -> impl Future<Item = Vec<u8>, Error = Error> {
    /* ... */
}

fn upload_to_server(data: Vec<u8>) -> impl Future<Item = usize, Error = Error> {
    /* ... */
}

// Uses `or_else` to do work on failure
fn download() -> impl Future<Item = Vec<u8>, Error = Error> {
    download_from_server(0)
        .or_else(|_| download_from_server(1))
        .or_else(|_| download_from_server(2))
}

// Uses `and_then` to do work on success
fn reupload() -> impl Future<Item = usize, Error = Error> {
    download().and_then(|data| upload_to_server(data))
}

// Uses `then` to always do work
fn do_things() -> impl Future<Item = (), Error = ()> {
    reupload().then(|r| {
        match r {
            Ok(size) => println!("Uploaded {} bytes", size),
            Err(_) => println!("Got an error"),
        };
        Ok(())
    })
}

Some cases are simplified by the async / await syntax stabilized in Rust 1.39:

// Equivalent to `or_else`
async fn download() -> Result<Vec<u8>, Error> {
    match download_from_server(0).await {
        Ok(v) => Ok(v),
        Err(_) => match download_from_server(1).await {
            Ok(v) => Ok(v),
            Err(_) => download_from_server(2).await,
        },
    }
}

// Equivalent to `and_then`
async fn reupload() -> Result<usize, Error> {
    let data = download().await?;
    upload_to_server(data).await
}

// Equivalent to `then`
async fn do_things() -> Result<(), ()> {
    match reupload().await {
        Ok(size) => println!("Uploaded {} bytes", size),
        Err(_) => println!("Got an error"),
    }
    Ok(())
}


来源:https://stackoverflow.com/questions/55552413/what-is-the-difference-between-then-and-then-and-or-else-in-rust-futures

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!