具有特征的 tokio-async-await
tokio-async-await with trait
我想在特征中编写异步函数,但由于特征中的 async fn
尚不支持,我正在尝试寻找等效的方法接口。这是我在 Rust nightly (2019-01-01) 中尝试过的:
#![feature(await_macro, async_await, futures_api)]
#[macro_use]
extern crate tokio;
use tokio::prelude::*;
trait T {
async fn f();
}
fn main() {
}
error[E0706]: trait fns cannot be declared `async`
--> src/main.rs:7:5
|
7 | async fn f();
| ^^^^^^^^^^^^^
我在某处读到 async
只是 impl Future
。
trait T {
fn f() -> impl futures::Future<Item = (), Error = ()>;
}
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src/lib.rs:2:15
|
2 | fn f() -> impl futures::Future<Item = (), Error = ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
不允许直接返回impl trait
,所以我尝试了一个盒装特征:
trait Resource {
fn loaded(&self) -> bool;
fn init(&mut self, auth: &str) -> Box<dyn std::future::Future<Output=()>>;
fn prepare(&mut self, auth: &str) -> Box<dyn std::future::Future<Output=()>> {
Box::new(async {
if !self.loaded() {
await!(*(self.init(auth)));
}
})
}
}
[rustc] the size for values of type `dyn std::future::Future<Output=()>` cannot be known at compilation time
如果没有 deref,我会得到这样的错误,即 Box<>.
不存在 into_awaitable
我可以将非 Sized impl Future
或 *Box<Future>
与 await!
一起使用吗? trait中异步函数最适合的接口是什么?
特征中不允许使用 async
函数和 impl Trait
。您可以使用关联类型来拉近距离。以下是一些想法:
pub trait ResourceTrait {
type FutType: Future<Output = ()>;
fn prepare(&mut self, auth: &str) -> Self::Next;
}
目前实现这个有点棘手,因为一些必需的工具尚不可用、稳定或有问题。
可以实现为:
impl ResourceTrait for Resource {
type FutType = FutureObj<'static, ()>;
fn prepare(&mut self, auth: &str) -> FutureObj<'static, ()> {
FutureObj::new(Box::new(
async move {
// Do async things
// You might get a lifetime issue here if trying to access auth,
// since it's borrowed.
}
))
}
}
存在类型的替代方案可能是:
impl ResourceTrait for Resource {
// this is required since the real type of the async function
// is unnameable
existential type FutType = Future<Output = ()>;
fn prepare(&mut self, auth: &str) -> Self::FutType {
async move {
// Do async things. Might still encounter the same borrowing issues,
// since the lifetime of the returned Future isn't coupled to the
// lifetime of self.
// The workaround is to make copies of all required fields and move
// them into the Future
}
}
}
这可能有效也可能无效(因为该功能正在开发中)。
为了在返回的 future 中正确借用 self
或 auth
等参数,我们可能还需要首先提供通用关联类型。
为了解决 self
的借用问题,您可以定义
struct Resource {
inner: Arc<ResourceInner>, // carries all actual state
}
以便您可以在 prepare
中复制 inner
并将其移动到 Future
。
如果您不介意返回盒装的未来,您可以使用 async-trait
板条箱:
#![feature(async_await)]
use async_trait::async_trait;
#[async_trait]
trait Advertisement {
async fn run(&self);
}
struct Modal;
#[async_trait]
impl Advertisement for Modal {
async fn run(&self) {
self.render_fullscreen().await;
for _ in 0..4u16 {
remind_user_to_join_mailing_list().await;
}
self.hide_for_now().await;
}
}
struct AutoplayingVideo {
media_url: String,
}
#[async_trait]
impl Advertisement for AutoplayingVideo {
async fn run(&self) {
let stream = connect(&self.media_url).await;
stream.play().await;
// Video probably persuaded user to join our mailing list!
Modal.run().await;
}
}
我想在特征中编写异步函数,但由于特征中的 async fn
尚不支持,我正在尝试寻找等效的方法接口。这是我在 Rust nightly (2019-01-01) 中尝试过的:
#![feature(await_macro, async_await, futures_api)]
#[macro_use]
extern crate tokio;
use tokio::prelude::*;
trait T {
async fn f();
}
fn main() {
}
error[E0706]: trait fns cannot be declared `async`
--> src/main.rs:7:5
|
7 | async fn f();
| ^^^^^^^^^^^^^
我在某处读到 async
只是 impl Future
。
trait T {
fn f() -> impl futures::Future<Item = (), Error = ()>;
}
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src/lib.rs:2:15
|
2 | fn f() -> impl futures::Future<Item = (), Error = ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
不允许直接返回impl trait
,所以我尝试了一个盒装特征:
trait Resource {
fn loaded(&self) -> bool;
fn init(&mut self, auth: &str) -> Box<dyn std::future::Future<Output=()>>;
fn prepare(&mut self, auth: &str) -> Box<dyn std::future::Future<Output=()>> {
Box::new(async {
if !self.loaded() {
await!(*(self.init(auth)));
}
})
}
}
[rustc] the size for values of type `dyn std::future::Future<Output=()>` cannot be known at compilation time
如果没有 deref,我会得到这样的错误,即 Box<>.
into_awaitable
我可以将非 Sized impl Future
或 *Box<Future>
与 await!
一起使用吗? trait中异步函数最适合的接口是什么?
特征中不允许使用 async
函数和 impl Trait
。您可以使用关联类型来拉近距离。以下是一些想法:
pub trait ResourceTrait {
type FutType: Future<Output = ()>;
fn prepare(&mut self, auth: &str) -> Self::Next;
}
目前实现这个有点棘手,因为一些必需的工具尚不可用、稳定或有问题。
可以实现为:
impl ResourceTrait for Resource {
type FutType = FutureObj<'static, ()>;
fn prepare(&mut self, auth: &str) -> FutureObj<'static, ()> {
FutureObj::new(Box::new(
async move {
// Do async things
// You might get a lifetime issue here if trying to access auth,
// since it's borrowed.
}
))
}
}
存在类型的替代方案可能是:
impl ResourceTrait for Resource {
// this is required since the real type of the async function
// is unnameable
existential type FutType = Future<Output = ()>;
fn prepare(&mut self, auth: &str) -> Self::FutType {
async move {
// Do async things. Might still encounter the same borrowing issues,
// since the lifetime of the returned Future isn't coupled to the
// lifetime of self.
// The workaround is to make copies of all required fields and move
// them into the Future
}
}
}
这可能有效也可能无效(因为该功能正在开发中)。
为了在返回的 future 中正确借用 self
或 auth
等参数,我们可能还需要首先提供通用关联类型。
为了解决 self
的借用问题,您可以定义
struct Resource {
inner: Arc<ResourceInner>, // carries all actual state
}
以便您可以在 prepare
中复制 inner
并将其移动到 Future
。
如果您不介意返回盒装的未来,您可以使用 async-trait
板条箱:
#![feature(async_await)]
use async_trait::async_trait;
#[async_trait]
trait Advertisement {
async fn run(&self);
}
struct Modal;
#[async_trait]
impl Advertisement for Modal {
async fn run(&self) {
self.render_fullscreen().await;
for _ in 0..4u16 {
remind_user_to_join_mailing_list().await;
}
self.hide_for_now().await;
}
}
struct AutoplayingVideo {
media_url: String,
}
#[async_trait]
impl Advertisement for AutoplayingVideo {
async fn run(&self) {
let stream = connect(&self.media_url).await;
stream.play().await;
// Video probably persuaded user to join our mailing list!
Modal.run().await;
}
}