簡體   English   中英

Rust async_trait 返回 `impl Stream`?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM