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