use std::io;
use thiserror::Error;
// 自定义解析错误
#[derive(Error, Debug)]
pub enum ResponseParseError {
#[error("Invalid response format")]
InvalidFormat,
}
// 模拟网络请求函数
async fn mock_network_request<T>(url: &str) -> Result<T, io::Error> where T: std::str::FromStr {
// 实际实现中这里会进行网络请求并返回结果
Ok("".parse().map_err(|_| io::Error::new(io::ErrorKind::Other, "parse error"))?)
}
// 解析响应函数
fn parse_response<T>(response: &str) -> Result<T, ResponseParseError> where T: std::str::FromStr {
response.parse().map_err(|_| ResponseParseError::InvalidFormat)
}
// 泛型函数处理多个请求
async fn process_requests<T>(urls: &[&str]) -> Result<Vec<T>, RequestError> where T: std::str::FromStr {
let mut results = Vec::new();
for url in urls {
let response = mock_network_request::<T>(url).await?;
let parsed = parse_response(&response.to_string())?;
results.push(parsed);
}
Ok(results)
}
// 统一错误类型
#[derive(Error, Debug)]
pub enum RequestError {
#[error("Network error: {0}")]
Network(#[from] io::Error),
#[error("Parse error: {0}")]
Parse(#[from] ResponseParseError),
}
// 顶层异步函数及错误处理
#[tokio::main]
async fn main() {
let urls = &["url1", "url2"];
match process_requests::<i32>(urls).await {
Ok(results) => println!("Results: {:?}", results),
Err(e) => eprintln!("Error: {:?}", e),
}
}
- 自定义解析错误:定义了
ResponseParseError
枚举类型来表示解析响应时的格式错误。
- 模拟网络请求函数:
mock_network_request
函数模拟实际的网络请求,它是异步的,并返回Result<T, io::Error>
,其中T
是可以从字符串解析的类型。
- 解析响应函数:
parse_response
函数将字符串解析为指定类型T
,如果解析失败返回ResponseParseError
。
- 泛型函数处理多个请求:
process_requests
函数是泛型函数,接受一个URL数组,对每个URL发起网络请求,解析响应,并将结果收集到一个Vec
中。它使用Result
处理网络错误和解析错误,并通过?
操作符合理构建错误链。
- 统一错误类型:
RequestError
枚举类型将网络错误和解析错误统一起来,方便在顶层进行处理。
- 顶层异步函数及错误处理:在
main
函数中,调用process_requests
并通过match
语句处理可能出现的错误。