Hello everyone,
I am really confused with a feature I'm trying to implement, let's say I have a Vec<Object>
which I am trying to serialize, then trying to send a POST request with the serialized body.
It would look like this :
vec.into_iter()
.map(|object| serde_json::to_string(&object) )
.map(|str_object| client.post().body(str_object).send().await )
The first map will return a Result<String, serde_error::Error>
while the second map will return a Result<String, reqwest::Error>
So that would obviously not compile, as the documentation says :
Maps a Result<T, E>
to Result<U, E>
What is an idomatic way to manage error properly in a functional fashion ? do I have to create my own error type to wrap those error in each map ?
The docs of map
you mentioned are from Result's map: Result in core::result - Rust
But the map
you're calling is Iterator's map: Iterator in std::iter - Rust
The code you posted wouldn't compile, but for different reasons. The first map
maps each Object
into a Result<String, serde_error::Error>
as you say. The second map
then maps each Result<String, serde_error::Error>
, which you then try to give to client.post().body(str_object)
, but you can't pass any Result to .body()
, no matter what the Error type. You also can't .await
inside a non-async closure.
There are ways to handle errors and async when using iterator combinators, but in this case the idiomatic way is to keep it simple with a for loop:
for object in vec {
let str_object = serde_json::to_string(&object)?;
client.post().body(str_object).send().await?;
}
You can do that, and that's typically the approach taken by library code. See thiserror - Rust to make it more convenient.
You can also use a general error type that allow you to convert most other errors into them. Box<dyn Error>
, anyhow::Error
or eyre::Error
are some such types. For example
async fn send_objects() -> Result<(), anyhow::Error> {
let client = get_client_from_somewhere();
let objects = get_vec_of_objects_from_somewhere();
for object in objects {
let str_object = serde_json::to_string(&object)?;
client.post().body(str_object).send().await?;
}
Ok(())
}
2 Likes
Sorry for the piece of code i've given, I tried to make it simple, but I introduced lots of mistake.
Thank you, this is an amazing answer. I wasn't aware of many things you told me.