![](/img/trans.png)
[英]How to return simple type from async method on a rust async_trait?
[英]Rust async_trait return `impl Stream`?
我想為現有的異步 class 編寫一個模擬,而無需對原始 class 進行太多更改。
為了演示我的問題,我從Guillaume Endignoux Blog 獲取了源代碼。
我想將其更改為async trait
:
use std::time::{Duration, Instant};
use async_trait::async_trait;
use futures::{StreamExt as _, Stream, stream};
use lazy_static::lazy_static;
use rand::distributions::{Uniform, Distribution as _};
use tokio::time::sleep;
lazy_static! {
static ref START_TIME: Instant = Instant::now();
}
struct Pages;
#[tokio::main]
async fn main() {
println!("First 10 pages:\n{:?}", Pages::get_n_pages(10).await);
}
#[async_trait]
trait Page {
async fn get_page(i: usize) -> Vec<usize>;
async fn get_n_pages(n: usize) -> Vec<Vec<usize>>;
fn get_pages() -> impl Stream<Item = Vec<usize>>;
}
#[async_trait]
impl Page for Pages {
async fn get_page(i: usize) -> Vec<usize> {
let millis = Uniform::from(0..10).sample(&mut rand::thread_rng());
println!(
"[{}] # get_page({}) will complete in {} ms",
START_TIME.elapsed().as_millis(),
i,
millis
);
sleep(Duration::from_millis(millis)).await;
println!(
"[{}] # get_page({}) completed",
START_TIME.elapsed().as_millis(),
i
);
(10 * i..10 * (i + 1)).collect()
}
async fn get_n_pages(n: usize) -> Vec<Vec<usize>> {
Self::get_pages().take(n).collect().await
}
fn get_pages() -> impl Stream<Item = Vec<usize>> {
stream::iter(0..).then(|i| Self::get_page(i))
}
}
但后來我收到消息: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return
中使用。
所以我將其更改為dyn
,但隨后我收到消息: doesn't have a size known at compile-time
。
有沒有一種方法可以編寫返回一種impl Stream<Item = Vec<usize>>
的async traits
?
據我了解,是的,有一種方法可以編寫返回一種 impl Stream<Item = Vec> 的異步特征。 您的代碼的問題是實現方法的返回類型中不允許使用 impl Trait。 相反,您可以使用 Box<dyn Stream<Item = Vec> 作為返回類型。 這表明返回值是一個裝箱特征 object,它可用於保存任何實現 Stream 特征的類型。
以下是更新代碼的方法:
#[async_trait]
impl Page for Pages {
// ...
fn get_pages() -> Box<dyn Stream<Item = Vec<usize>> + Send> {
Box::new(stream::iter(0..).then(|i| Self::get_page(i)))
}
}
通過這種方式,您可以使用異步特性並返回一種 impl Stream<Item = Vec>,但請記住,+ Send 是必需的,因為基於 tokio 的流是 Send,這是 Box 特性 object 的要求。不要引用我的話,因為我的知識和理解是有限的,但請隨時問我任何進一步的問題。
有一個不穩定的特性允許impl Trait
在特征的返回位置return_position_impl_trait_in_trait
。 有了它,您可以使用您的初始語法,但需要每晚運行:
#![feature(return_position_impl_trait_in_trait)]
use async_trait::async_trait;
use futures::{StreamExt as _, Stream, stream};
#[async_trait]
impl Page for Pages {
//...
fn get_pages() -> impl Stream<Item = Vec<usize>> {
stream::iter(0..).then(|i| Self::get_page(i))
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.