请教一个封装返回自定义错误的问题?

作者站长头像
站长
· 阅读数 12

我尝试对reqwest工具进行一下简单的封装,遇到一个返回自定义错误的问题,如下代码:

type st = Pin<Box<dyn Stream<Item = Result<bytes::Bytes, reqwest::Error>> + Send>>
let mut stream: st  = resp.bytes_stream().boxed();

这里流会返回reqwest::Error类型的错误,请问如果我想返回自定义错误应该如何做? 大概类似下面这样返回自定义错误MyError。

type st = Pin<Box<dyn Stream<Item = Result<bytes::Bytes, MyError>> + Send>>

谢谢。

回复
1个回答
avatar
test
2024-07-05

你可以使用map_err函数将reqwest::Error类型的错误转换为你自定义的MyError类型的错误,例如:

use std::convert::Infallible;
use std::error::Error;
use std::fmt;

use bytes::Bytes;
use reqwest::Client;
use tokio::stream::Stream;
use tokio::stream::StreamExt;
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
use tokio::task::JoinHandle;

#[derive(Debug)]
struct MyError(String);

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "MyError: {}", self.0)
    }
}

impl Error for MyError {}

impl From<Infallible> for MyError {
    fn from(_: Infallible) -> Self {
        panic!("Infallible value created")
    }
}

impl From<reqwest::Error> for MyError {
    fn from(error: reqwest::Error) -> Self {
        MyError(error.to_string())
    }
}

async fn fetch(url: String, tx: UnboundedSender<Result<Bytes, MyError>>) -> JoinHandle<()> {
    let client = Client::new();
    let resp = client.get(&url).send().await.unwrap();
    let mut stream = resp.bytes_stream();

    tokio::spawn(async move {
        while let Some(item) = stream.next().await {
            match item {
                Ok(bytes) => {
                    tx.send(Ok(bytes)).unwrap();
                }
                Err(error) => {
                    tx.send(Err(MyError::from(error))).unwrap();
                }
            }
        }
    })
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let (tx, rx) = unbounded_channel();

    tokio::spawn(fetch(String::from("https://www.rust-lang.org"), tx));

    let mut rx = rx.fuse();

    while let Some(item) = rx.next().await {
        match item {
            Ok(bytes) => println!("{}", bytes.len()),
            Err(error) => println!("{}", error),
        }
    }

    Ok(())
}

在这个例子中,将reqwest::Error类型的错误转换为了自定义的MyError类型的错误,然后使用UnboundedSender<Result<Bytes, MyError>>发送数据。使用UnboundedReceiver<Result<Bytes, MyError>>接收数据时,可以使用match语句将Result类型的值分别处理。

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容