Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Error handling 使用futures时是否有更符合人体工程学的语法?_Error Handling_Syntax_Rust_Future - Fatal编程技术网

Error handling 使用futures时是否有更符合人体工程学的语法?

Error handling 使用futures时是否有更符合人体工程学的语法?,error-handling,syntax,rust,future,Error Handling,Syntax,Rust,Future,下面是一个使用Tokio运行函数返回未来的示例: use futures::sync::oneshot; use futures::Future; use std::thread; use std::time::Duration; use tokio; #[derive(Debug)] struct MyError { error_code: i32, } impl From<oneshot::Canceled> for MyError { fn from(_:

下面是一个使用Tokio运行函数返回未来的示例:

use futures::sync::oneshot;
use futures::Future;
use std::thread;
use std::time::Duration;
use tokio;

#[derive(Debug)]
struct MyError {
    error_code: i32,
}

impl From<oneshot::Canceled> for MyError {
    fn from(_: oneshot::Canceled) -> MyError {
        MyError { error_code: 1 }
    }
}

fn deferred_task() -> impl Future<Item = i32, Error = MyError> {
    let (sx, rx) = oneshot::channel();
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(100));
        sx.send(100).unwrap();
    });
    return rx.map_err(|e| MyError::from(e));
}

fn main() {
    tokio::run(deferred_task().then(|r| {
        println!("{:?}", r);
        Ok(())
    }));
}
fn send_promise_to_worker(sx: oneshot::Sender<i32>) -> Result<(), ()> {
    // Send the oneshot somewhere in a way that might fail, eg. over a channel
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(100));
        sx.send(100).unwrap();
    });
    Ok(())
}

fn deferred_task() -> impl Future<Item = i32, Error = MyError> {
    let (sx, rx) = oneshot::channel();
    send_promise_to_worker(sx)?; // <-------- Can't do this, because the return is not a result
    return rx.map_err(|e| MyError::from(e));
}
fn deferred_task() -> impl Future<Item = i32, Error = MyError> {
    let (tx, rx) = oneshot::channel();

    query_data()
        .map_err(|_| MyError { error_code: 1 })
        .into_future()
        .and_then(|_i| {
            send_promise_to_worker(tx)
                .map_err(|_| MyError { error_code: 2 })
                .into_future()
        })
        .and_then(|_| rx.map_err(MyError::from))
}
Future
是一个
Result
,在Result中包装它是没有意义的,它会破坏
impl Future
返回类型

取而代之的是一个深度嵌套的链:

fn deferred_task() -> impl Future<Item = i32, Error = MyError> {
    let (sx, rx) = oneshot::channel();
    match query_data() {
        Ok(_i) => match send_promise_to_worker(sx) {
            Ok(_) => Either::A(rx.map_err(|e| MyError::from(e))),
            Err(_e) => Either::B(futures::failed(MyError { error_code: 2 })),
        },
        Err(_) => Either::B(futures::failed(MyError { error_code: 2 })),
    }
}
fn延迟的任务()->impl Future{
let(sx,rx)=oneshot::channel();
匹配查询_数据(){
Ok(_i)=>匹配发送承诺给员工(sx){
Ok(|)=>A(rx.map_err(| e | MyError::from(e)),
Err(_e)=>B(futures::failed(MyError{error_code:2})),
},
Err()=>B(futures::failed(MyError{error_code:2})),
}
}

结果越多,嵌套越深;正是
运算符正常解决的问题

我错过什么了吗?是否有一些语法糖可以让这更容易

是否有一些语法糖可以让这更容易

是的,它被称为async/await,但它还没有准备好广泛使用。它只在夜间受支持,它使用了与Tokio稍有不同的futures版本,Tokio只通过一个互操作库支持该版本,这会导致额外的语法开销,而且整个过程的文档仍然不完整

以下是一些相关链接:




我看不出
async
/
wait
语法在
方面有什么绝对的帮助。最终,您仍然需要返回一个具体类型,这就是
提供的
async
/
await
将减少对组合器的需求,例如
Future::map
Future::and\u then

另见:


也就是说,这里也不需要使用

您有连续的
Result
-返回函数,因此您可以借用JavaScript的技巧,使用
操作符。然后,我们可以将组合的
结果
提升到未来,并将其与来自接收器的未来链接起来:

fn deferred_task() -> impl Future<Item = i32, Error = MyError> {
    let (tx, rx) = oneshot::channel();

    let x = (|| {
        let _i = query_data().map_err(|_| MyError { error_code: 1 })?;
        send_promise_to_worker(tx).map_err(|_| MyError { error_code: 2 })?;
        Ok(())
    })();

    future::result(x).and_then(|()| rx.map_err(MyError::from))
}
这将有助于使用
async
/
await
语法:

async fn deferred_task() -> Result<i32, MyError> {
    let (tx, rx) = oneshot::channel();

    query_data().map_err(|_| MyError { error_code: 1 })?;

    send_promise_to_worker(tx).map_err(|_| MyError { error_code: 2 })?;

    let v = await! { rx }?;

    Ok(v)
}
但是,这在当前的任何实现中都没有出现

未来
是一个
结果

不,不是

有两个相关的
未来
可以讨论:

值得注意的是,
Future::poll
返回的类型可以处于两种状态:

  • 完整的
  • 不完整
在futures板条箱中,“成功”和“失败”与“完成”关联,而在标准库中则不是。在板条箱中,
Result
实现,在标准库中可以使用。这两种方法都允许将
结果
转换为未来,但这并不意味着
结果
是未来,只不过说
Vec
是迭代器,即使它可以转换为迭代器

操作符(由
Try
特性提供动力)可能会被增强,以自动从
结果
转换为特定类型的
未来
,或者
结果
甚至会直接实现
未来
,但我还没有听说过这样的计划

foo.left();
// vs
Either::left(foo);