如何用Future替换组合器?

时间:2019-08-17 19:37:48

标签: asynchronous rust future

我有一个返回Future的函数。它接受另一个函数,该函数接受一个参数并返回Future。可以将第二个函数实现为传递到第一个函数的组合器链。看起来像这样:

use bb8::{Pool, RunError};
use bb8_postgres::PostgresConnectionManager;
use tokio_postgres::{error::Error, Client, NoTls};

#[derive(Clone)]
pub struct DataManager(Pool<PostgresConnectionManager<NoTls>>);

impl DataManager {
    pub fn new(pool: Pool<PostgresConnectionManager<NoTls>>) -> Self {
        Self(pool)
    }

    pub fn create_user(
        &self,
        reg_req: UserRequest,
    ) -> impl Future<Item = User, Error = RunError<Error>> {
        let sql = "long and awesome sql";

        let query = move |mut conn: Client| {  // function which accepts one argument and returns Future
            conn.prepare(sql).then(move |r| match r {
                Ok(select) => {
                    let f = conn
                        .query(&select, &[&reg_req.email, &reg_req.password])
                        .collect()
                        .map(|mut rows| {
                            let row = rows.remove(0);
                            row.into()
                        })
                        .then(move |r| match r {
                            Ok(v) => Ok((v, conn)),
                            Err(e) => Err((e, conn)),
                        });
                    Either::A(f)
                }
                Err(e) => Either::B(future::err((e, conn))),
            })
        };
        self.0.run(query)  // function which returns Future and accepts another function
    }
}

但是我想编写create_user的代码作为实现Future的结构。

struct UserCreator(Pool<PostgresConnectionManager<NoTls>>, UserRequest);

impl UserCreator {
    fn new(pool: Pool<PostgresConnectionManager<NoTls>>, reg_req: UserRequest) -> Self {
        Self(pool, reg_req)
    }
}

如何对该用作第一个功能的结构实现Future?请帮我举个例子。

现在我试图使它变成这样,但是没有计算任何东西,执行总是阻塞。

impl Future for UserCreator {
    type Item = User;
    type Error = RunError<Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // Code which which works like `DataManager.create_user`
        let sql = "long and awesome sql";
        let reg_req = &self.1;

        let query = move |mut conn: Client| {
            conn.prepare(sql).then(move |r| match r {
                Ok(select) => {
                    let f = conn
                        .query(&select, &[&reg_req.email, &reg_req.password])
                        .collect()
                        .map(|mut rows| {
                            let row = rows.remove(0);
                            row.into()
                        })
                        .then(move |r| match r {
                            Ok(v) => Ok((v, conn)),
                            Err(e) => Err((e, conn)),
                        });
                    Either::A(f)
                }
                Err(e) => Either::B(future::err((e, conn))),
            })
        };
        self.0.run(query).poll()
    }
}

0 个答案:

没有答案