В чем разница между `then`,` and_then` и `or_else` в фьючерсах Rust? - PullRequest
1 голос
/ 06 апреля 2019

Я учусь использовать фьючерсы на Rust и нахожу это крайне запутанным. Я чувствую себя глупо, но когда будут использоваться then, and_then и or_else? Какие возвращаемые типы ожидаются?

Пожалуйста, приведите несколько примеров различных ситуаций, которые вы ожидаете увидеть.

1 Ответ

4 голосов
/ 06 апреля 2019

TL; DR: then используется, когда вы хотите что-то сделать независимо от того, было ли будущее успешным, and_then выполняет закрытие только тогда, когда будущее успешно, и or_else запускает закрытие только тогда, когдабудущее не удалось.

and_then и or_else являются прямыми аналогами методам с тем же именем в Result.


Ваш первый шаг должен состоять в чтении документации.Документация содержит точные сигнатуры методов (которые объясняют, какие типы он ожидает и какие возвращаемые типы), проза, описывающую каждый метод, а также пример использования.

Я выделил небольшие фрагменты документов и подчеркнулсоответствующие части.

Future::then:

Эта функция может использоваться для обеспечения вычисления, выполняемого независимо от заключения о будущем .Предоставленное замыкание получит Result после завершения будущего.

Возвращаемое значение замыкания должно реализовывать черту IntoFuture и может представлять некоторую дополнительную работу, которую необходимо выполнить до завершения составного будущего..

Future::and_then:

Эта функция может использоваться для объединения двух фьючерсов и обеспечения того, что окончательное будущее не будет решено дооба закончили.Предоставленное закрытие дает успешный результат этого будущего и возвращает другое значение, которое может быть преобразовано в будущее.

Future::or_else

Возвращает будущее, которое передает значение этого будущего, если оно успешно, и в противном случае передает ошибку закрытию f и ждет будущего, которое оно возвращает.

Тип возврата для всех трех методов - это любой тип, который можно преобразовать в другое будущее.

  • then: никаких дополнительных ограничений на тип возврата нет.
  • and_then требует, чтобы тип ошибки возвращенного будущего совпадал с типом ошибки начального будущего.
  • or_else требует, чтобы тип успеха возвращенного будущего совпадал с типом успеха начального будущего.

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(())
    })
}
...