2

下面的函数,取自这里

fn connection_for(
    &self,
    pool_key: PoolKey,
) -> impl Future<Output = Result<Pooled<PoolClient<B>>, ClientError<B>>> {

    let checkout = self.pool.checkout(pool_key.clone());
    let connect = self.connect_to(pool_key);

    let executor = self.conn_builder.exec.clone();
    // The order of the `select` is depended on below...
    future::select(checkout, connect).then(move |either| match either {
         ...

应该返回一个Future. 但是,它返回的返回结果

    future::select(checkout, connect).then(...)

这是在哪里.then

fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F>

哪个不是Future. 这怎么可能?

我试图了解此函数返回的内容。这是'.then'的结尾:

       Either::Right((Err(err), checkout)) => Either::Right(Either::Right({
            if err.is_canceled() {
                Either::Left(checkout.map_err(ClientError::Normal))
            } else {
                Either::Right(future::err(ClientError::Normal(err)))
            }
        })),

看起来它返回Either::Right(Either::Right了一些东西。我很困惑。

4

1 回答 1

2

.then()用于将两个期货链接在一起。它返回 a Then<Fut1, Fut2, F>,这是 aFuture的工作:轮询第一个未来,用给定的函数处理结果,并轮询产生的未来。


Either类型旨在将具有相同关联输出的两个不同期货组合成一个类型。假设您正在创建一个函数,该函数将根据输入返回两个不同的期货:

async fn do_a() -> () {}
async fn do_b() -> () {}

fn do_something(cond: bool) -> impl Future<Output = ()> {
    if cond {
        do_a()
    }
    else {
        do_b()
    }
}

这不会编译,因为 和 返回的sFuture是不同的类型。Rust 编译器很友好地建议使用动态返回不同的类型,但是出于性能原因,有时不需要额外的间接性,也不是必需的。do_a()do_b()Box<dyn Future>

上面可以实现返回一个具体的Futureusing Either

use std::future::Future;
use futures::future::Either;

async fn do_a() -> () {}
async fn do_b() -> () {}

fn do_something(cond: bool) -> impl Future<Output = ()> {
    if cond {
        Either::Left(do_a())
    }
    else {
        Either::Right(do_b())
    }
}

有问题的链接代码看起来有点粗糙,因为它不仅要协调两个不同的未来,还要协调五个。Either但是你可以毫无问题地嵌套s,因为它们本身就是Futures。它更像这样:

use std::future::Future;
use futures::future::Either;

async fn do_a() -> () {}
async fn do_b() -> () {}
async fn do_c() -> () {}
async fn do_d() -> () {}
async fn do_e() -> () {}

fn do_something(cond1: bool, cond2: bool, cond3: bool) -> impl Future<Output = ()> {
    if cond1 {
        Either::Left(do_a())
    }
    else if cond2 {
        if cond3 {
            Either::Right(Either::Left(Either::Left(do_b())))
        }
        else {
            Either::Right(Either::Left(Either::Right(do_c())))
        }
    }
    else {
        if cond3 {
            Either::Right(Either::Right(Either::Left(do_d())))
        }
        else {
            Either::Right(Either::Right(Either::Right(do_e())))
        }
    }
}

这一切最终都创建了 a impl Future<Output = Result<Pooled<PoolClient<B>>, ClientError<B>>>,因为它可以潜在地产生每个收益 a 的所有单个期货Result<Pooled<PoolClient<B>>, ClientError<B>>

于 2021-02-18T08:10:23.507 回答