以下是使用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(())
}));
}
然而,当所讨论的函数(即< code>deferred_task)不是平凡的函数时,我编写的代码会变得更加复杂,因为< code >?操作似乎不容易与返回未来相混合:
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));
}
Future
是一个结果
,将其包装在结果中是没有意义的,它打破了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 })),
}
}
完整代码
结果越多,嵌套越深;到底是什么?
运算符通常会解决。
我错过了什么吗?有没有一些语法糖来使这更容易?
有没有一些语法糖来使这更容易?
是的,它被称为异步/等待,但它还没有准备好广泛消费。它只支持每晚,它使用稍微不同的期货版本,Tokio只通过互操作库支持,这会导致额外的语法开销,整个事情的文档仍然参差不齐。
以下是一些相关链接:
Rust中异步/等待的目的是什么
https://jsdw.me/posts/rust-asyncawait-preview/
这是一个很好的例子https://areweasyncyet.rs/
我看不出< code > async /< code > await 语法将如何明确地帮助您使用< code >要么。最终,您仍然需要返回一个具体类型,这就是< code >要么所提供的。然而,< code > async /< code > await 将减少对像< code>Future::map或< code>Future::and_then这样的组合器的需求。
另请参阅:
这就是说,您也不需要在此处使用。
您有连续的< code>Result
返回函数,所以您可以借鉴JavaScript的技巧,使用IIFE来使用< code >?操作员。然后,我们可以将组合的< code >结果提升到未来,并将其与来自接收器的未来链接起来:
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))
}
据我所知,在未来,iLife可能会被try
块取代。
您也可以走另一条路,将所有内容转换为未来:
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))
}
这将有助于< code > async /< code > 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
特征添加左
和右
方法来构造 Either
的改进语法:
foo.left();
// vs
Either::left(foo);
但是,这不会出现在任何当前实现中。
一个Future
是一个Result
不,不是的。
有两个相关的未来
可以谈论:
值得注意的是,Future::投票
返回一种可以处于两种状态的类型:
在期货板条箱中,“成功”和“失败”与“完成”相关联,而在标准库中则不然。在板条箱中,Result
实现了IntoFuture
,在标准库中,您可以使用Future::就绪
。这两者都允许将Result
转换为未来,但这并不意味着Result
是一个未来,只不过是说Vec
有可能是<代码>?
运算符(由< code>Try特征提供支持)将得到增强,自动从< code >结果转换为特定类型的< code >未来,或者< code >结果甚至将直接实现< code >未来,但是我没有听说过任何这样的计划。
所以我想要一个“Void Repository”,通过它可以访问不一定在实体上操作的存储过程。 但这当然不起作用,因为期望是一个实体。 有没有一种方法可以使用注释而无需创建虚拟实体,或者我是否坚持使用使用通过准备好的语句进行查询的已实现类? 因为老实说,这很难看:
问题内容: 我正在使用我给定的语言环境获取自定义货币格式。但是,这始终包含我不需要的货币符号,我只想要给定语言环境的正确货币数字格式而没有货币符号。 做一个抛出一个异常.. 问题答案: 以下作品。这有点丑陋,但可以履行合同: 您还可以从货币格式中获取模式,删除货币符号,然后从新模式中重构新格式:
问题内容: 我的意思是可以在Win32和Linux i386中都运行一个二进制文件吗? 问题答案: 这是不可能的,因为两种类型的格式有冲突: PE文件的开头两个字符必须是; ELF文件的开头四个字符必须为。 显然,您不能创建一个可以同时满足两种格式的文件。 回应有关多语言二进制文件同时作为16位COM文件和Linux ELF文件都有效的评论,这是有可能的(尽管COM文件实际上是DOS程序,而不是W
问题内容: 我正在尝试根据语言环境获取货币符号。但是,它不是返回符号,而是返回代码。我有一个摘要: 对于 Locale.US, 它给出了符号,但是如果我替换 与 然后,用符号代替国家代码。为什么会这样以及如何获取符号? 编辑: 在寻找了一些答案之后,我想清除一下,设置一些特定的默认本地不是解决方案,因为 我需要一次显示所有可用的符号 。 例如 会给我欧元符号,但对于美元,它将给出代码,而不是美元符
我已经将Python discord机器人部署到Heroku并启用了自动部署,但是当我转到参考资料时,我在任何地方都看不到worker,即使我已经部署了它。此外,我使用的是Github,而不是CLI (据我所知,没有文件)
问题内容: 在过滤掉冗余信息时,我需要组合两个字符串集,这是我想出的解决方案,有没有人可以建议的更好方法?也许我忽略了内置的东西?谷歌没有任何运气。 问题答案: 由于a 不包含重复的条目,因此可以通过以下方式将两者合并: 两次添加都没有关系,该集合只包含一次元素…例如,不需要使用method 进行检查。