我需要處理來自幾個不同來源的異步資料流,這些資料流都應該被決議成某種規范化格式。
理想情況下,我想:
為實作某些特征的每個源撰寫一個處理程式,
Handler以便下游呼叫者可以與資料流互動,并且與底層實作無關。有一些函式可以回傳
Box<dyn Handler>給定的鍵,因為Handler實作的源數量有限/可預測。
我已經嘗試過類似以下的使用#[async_trait],但我無法編譯它,主要是錯誤“Handler無法將特征制成物件”。
有沒有更好/更慣用的方法來解決這個問題?
use async_trait; // 0.1.52
use tokio; // 1.15.0
#[async_trait::async_trait]
trait Handler{
type Output;
async fn connect()->Self::Output;
async fn read_parse(&self)->Vec<i32>;
async fn run(&self) {
for _ in 0..5 {
self.read_parse().await;
}
}
}
struct FooHandler;
#[async_trait::async_trait]
impl Handler for FooHandler {
type Output = FooHandler;
async fn connect() -> Self::Output {
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
FooHandler{}
}
async fn read_parse(&self)->Vec<i32> {
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
vec![1, 2, 3]
}
}
struct BarHandler;
#[async_trait::async_trait]
impl Handler for BarHandler {
type Output = BarHandler;
async fn connect() -> Self::Output {
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
BarHandler{}
}
async fn read_parse(&self)->Vec<i32> {
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
vec![1, 2, 3]
}
}
async fn get_handler(name:&str)->Option<Box<dyn Handler>> {
match name {
"FOO"=>Some(Box::new(FooHandler::connect().await)),
"BAR"=>Some(Box::new(BarHandler::connect().await)),
_=>None
}
}
#[tokio::main]
async fn main() {
let handler = get_handler("FOO").await.unwrap();
handler.run().await;
}
編輯:
根據 cameron1024 的回答,我能夠使以下作業:
use async_trait; // 0.1.52
use tokio; // 1.15.0
#[async_trait::async_trait]
trait Handler: Sync {
async fn connect()->Self
where
Self: Sized;
async fn read_parse(&self)->Vec<i32>;
async fn run(&self) {
for _ in 0..5 {
let res = self.read_parse().await;
println!("{:?}", res);
}
}
}
struct FooHandler;
#[async_trait::async_trait]
impl Handler for FooHandler {
async fn connect() -> Self {
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
println!("connected");
FooHandler{}
}
async fn read_parse(&self)->Vec<i32> {
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
vec![1, 2, 3]
}
}
async fn get_handler(name: &str)->Option<Box<dyn Handler>> {
match name {
"FOO"=>Some(Box::new(FooHandler::connect().await)),
_=>None
}
}
#[tokio::main]
async fn main() {
// let handler = FooHandler::connect().await;
let handler = get_handler("FOO").await.unwrap();
handler.run().await;
}
uj5u.com熱心網友回復:
這里有2個問題。
首先,對于具有默認實作的異步特征,它要求特征本身具有Send或Sync(取決于接收器型別)作為超級特征(在 crate 的自述檔案的“dyn 特征”部分中有簡要說明:https ://docs.rs/async-trait/latest/async_trait/)
其次,該connect函式不是物件安全的,因為它的回傳型別是關聯函式。這與異步無關,這是一個物件安全問題。這個簡化的例子有同樣的問題:
fn main() {
let x: Box<dyn Foo<Bar = ()>> = Box::new(());
}
trait Foo {
type Bar;
fn connect() -> Self::Bar;
}
impl Foo for () {
type Bar = ();
fn new() -> Self::Bar {
todo!()
}
}
但是,您不太可能希望connect在 trait 物件上呼叫,因為它沒有self引數。相反,您可以通過將Self: Sized約束添加到connect.
然后您可以創建一個特征物件,但connect將不可用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/411869.html
標籤:
上一篇:按需更新React輸入欄位值
