如何在期货链中使用包含在结果类型中的套接字?

How to use a socket contained in the Result type in a chain of futures?

我对 Tokio 文档中的以下工作代码稍作修改:

// Task
let connection = io::read_exact(socket, buf_read)
    .and_then(|(socket, buf_read)| {
        println!("Do something with the received data...");
        for b in &buf_read {
            println!("{}", b);
        }

        // Write to the socket
        let buf_write = vec![19; 30];
        io::write_all(socket, buf_write)
    })
    .then(|res| {
        println!("{:?}", res); // Just for testing
        //Output: Ok((TcpStream, [19, 19, 19, ...]

        println!("Send data...");
        let buf_write = vec![18; 10]; // Fill the buffer with some data
        //
        //How to use the socket contained in res to write the data to the socket
        //    
        Ok(())
    });

the docs it is mentioned

Note that res is a Result that contains the original socket. This allows us to sequence additional reads or writes on the same socket.

如何使用Result中包含的套接字向套接字写入数据?

请重新阅读 The Rust Programming Language, specifically the chapter on Recoverable Errors with Result. Then re-read the documentation for the library you are using

Future::then,强调我的:

fn then<F, B>(self, f: F) -> Then<Self, B, F>
where
    F: FnOnce(Result<Self::Item, Self::Error>) -> B,
    B: IntoFuture,
    Self: Sized,

Chain on a computation for when a future finished, passing the result of the future to the provided closure f.

This function can be used to ensure a computation runs regardless of the conclusion of the future. The closure provided will be yielded a Result once the future is complete.

将此与您正在使用的 other 函数进行对比,Future::and_then,强调我的:

fn and_then<F, B>(self, f: F) -> AndThen<Self, B, F>
where
    F: FnOnce(Self::Item) -> B,
    B: IntoFuture<Error = Self::Error>,
    Self: Sized, 

Execute another future after this one has resolved successfully.

This function can be used to chain two futures together and ensure that the final future isn't resolved until both have finished. The closure provided is yielded the successful result of this future and returns another value which can be converted into a future.


一个解决方案是仅通过 and_then:

成功处理它
extern crate tokio; // 0.1.7

use tokio::{io, net::TcpStream, prelude::*};

fn example(socket: TcpStream, buf_read: Vec<u8>) {
    io::read_exact(socket, buf_read)
        .and_then(|(socket, buf_read)| {
            let buf_write = vec![19; 30];
            io::write_all(socket, buf_write)
        }).and_then(|(socket, data)| {
            let buf_write = vec![18; 10];
            io::write_all(socket, buf_write)
        });
    // TODO: use future somehow 
}

如果您想知道失败的原因,那么您可以继续使用 then 但您将不得不以某种方式处理错误:

fn example(socket: TcpStream, buf_read: Vec<u8>) {
    io::read_exact(socket, buf_read)
        .and_then(|(socket, buf_read)| {
            let buf_write = vec![19; 30];
            io::write_all(socket, buf_write)
        }).then(|res| match res {
            Ok((socket, data)) => {
                let buf_write = vec![18; 10];
                io::write_all(socket, buf_write)
            }
            Err(e) => {
                // Do something with the error and return another
                // future that's type-compatible
                unimplemented!()
            },
        });
    // TODO: use future somehow
}

另请参阅:

  • What's the benefit of using a Result?