根据最初的未来结果有条件地链接 Rust 未来?

Conditionally chaining a Rust future based on initial future result?

如果我有一些链接在一起的期货,我怎样才能使第二个链接的期货以第一个期货的结果为条件?

举一个人为的例子,我有这样的东西:

extern crate futures;
extern crate tokio_core;

use futures::{future, Future};
use tokio_core::reactor::Core;

fn add_one(x: i64) -> impl Future<Item = i64, Error = ()> {
    future::ok(x).map(|x| x + 1)
}

fn double(x: i64) -> impl Future<Item = i64, Error = ()> {
    future::ok(x).map(|x| x * 2)
}

fn add_one_then_double(x: i64) -> impl Future<Item = i64, Error = ()> {
    future::ok(x).and_then(add_one).and_then(double)
}

fn main() {
    let mut reactor = Core::new().unwrap();
    println!("{:?}", reactor.run(add_one_then_double(10)).unwrap());
}

然后我怎样才能将 add_one_then_double 未来更改为以 add_one 未来的结果为条件,例如:

fn add_one_then_double_if_positive(x: i64) -> impl Future<Item = i64, Error = ()> {
    future::ok(x).and_then(add_one).map(|v| {
        if v >= 0 {
            // chain the `double` future
        } else {
            // return `v` as the result
        }
    })
}

如果你想链接另一个未来,你需要使用 and_then() 未来组合器,而不是 map()。该组合器期望另一个未来作为 return 值,因此 both 您的 if 语句的分支需要产生一个未来。在第一个分支中,你想要链接 double(v),这已经是一个未来。在第二个分支中,您希望传递不变的值,因此您需要将它变成一个使用 future::ok() 立即解析为 v 的 future。由于 double(v)future::ok(v) 的类型不同,您需要使用 future::Either,或者将期货装箱。这是一个选项:

fn add_one_then_double(x: i64) -> impl Future<Item=i64, Error=()> {
    future::ok(x)
        .and_then(add_one)
        .and_then(|v| {
            if v >= 0 {
                future::Either::A(double(v))
            } else {
                future::Either::B(future::ok(v))
            }
        })
}

Playground