您好,我正在使用 Leptos 实现一个 Rust 应用程序。我做了很多实验,同时也在学习,所以我做的事情可能不是最好的,但我想解决我看到的问题。这个问题是纯理论性的。我没有在我的生产中使用下面的客户端。对我来说,这只是一个有趣的案例。
我有以下实现
use serde::{Deserialize, de::DeserializeOwned, Serialize};
pub trait ApiResourceQuery {
fn path(&self) -> &str;
}
pub struct ApiRequestBuilder<'a, Q, H, H2> {
query: Q,
client: Option<&'a reqwest::Client>, // client is marked as optional only for this example
token: Option<&'a str>,
on_begin_func: Option<H>,
on_finish_func: Option<H2>,
}
impl<'a, Q, H, H2> ApiRequestBuilder<'a, Q, H, H2>
where
Q: ApiResourceQuery + Serialize,
H: FnOnce(),
H2: FnOnce(),
{
pub fn new(query: Q) -> Self {
ApiRequestBuilder {
query,
client: None,
token: None,
on_begin_func: None,
on_finish_func: None,
}
}
pub fn with_token(mut self, token: &'a str) -> Self {
self.token = Some(token);
self
}
pub fn with_client(mut self, client: &'a reqwest::Client) -> Self {
self.client = Some(client);
self
}
pub fn on_begin(mut self, func: H) -> Self {
self.on_begin_func = Some(func);
self
}
pub fn on_finish(mut self, func: H2) -> Self {
self.on_finish_func = Some(func);
self
}
pub /* async */ fn execute<R>(self, on_successful: impl FnOnce(R))
where
R: DeserializeOwned + Default, // default is temporary only for this example
{
if let Some(handler) = self.on_begin_func {
handler();
}
let res: Result<R, ()> = Ok(R::default());
on_successful(res.unwrap()); // unwrap only for the example purposes
if let Some(handler) = self.on_finish_func {
handler();
}
}
}
#[derive(Serialize, Deserialize)]
struct GetUserQuery {}
impl ApiResourceQuery for GetUserQuery {
fn path(&self) -> &str {
"/api/resource"
}
}
#[derive(Serialize, Deserialize, Debug)]
struct GetUserResponse {
pub username: String
}
impl Default for GetUserResponse {
fn default() -> Self {
Self {
username: "default username".into(),
}
}
}
我可以按以下方式使用它:
fn main() {
// Usecase 1
ApiRequestBuilder::new(GetUserQuery{})
.on_begin(||println!("On begin handler1"))
.on_finish(||println!("On finish handler1"))
.execute(|user: GetUserResponse| println!("On successful1: {:?}", user));
// Usecase 2
// <'a, Q, H, H2>
ApiRequestBuilder::<'_, _, _, fn()>::new(GetUserQuery{})
.on_begin(||println!("On begin handler2"))
.execute(|user: GetUserResponse| println!("On successful2: {:?}", user));
// Usecase 3 - won't compile
// <'a, Q, H, H2>
ApiRequestBuilder::new(GetUserQuery{})
.on_begin(||println!("On begin handler3"))
.execute(|user: GetUserResponse| println!("On successful3: {:?}", user));
}
问题出在用例 3 中,由于以下错误,它无法编译:
error[E0284]: type annotations needed
--> src/main.rs:111:5
|
111 | ApiRequestBuilder::new(GetUserQuery{})
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `H2` declared on the struct `ApiRequestBuilder`
|
= note: cannot satisfy `<_ as FnOnce<()>>::Output == ()`
note: required by a bound in `ApiRequestBuilder::<'a, Q, H, H2>::new`
--> src/main.rs:19:9
|
19 | H2: FnOnce(),
| ^^^^^^^^ required by this bound in `ApiRequestBuilder::<'a, Q, H, H2>::new`
20 | {
21 | pub fn new(query: Q) -> Self {
| --- required by a bound in this associated function
help: consider specifying the generic arguments
|
111 | ApiRequestBuilder::<GetUserQuery, _, H2>(GetUserQuery{})
| ~~~~~~~~~~~~~~~~~~~~~~~
当我想跳过一个回调时,有没有一种简单的方法可以提供默认值?它们可以在结构定义期间定义吗?这里的例子很简单,但如果我有另外 2 个回调怎么办,比如说:
on_expected_error
on_unexpected_error
当我要调用的时候用5种类型注释,不是很直观。
您可以通过指定默认类型来实现
new()
: