英文:
how to optimize the multi unwrap code statement in rust
问题
我正在学习使用Rust v1.65.0 发送HTTP请求。现在我有一个Rust代码块如下:
pub async fn get_queue_cv() {
    let client = Client::new();
    let url_path = "/cv/gen/v1/list";
    let url = format!("{}{}", get_app_config("cv.cv_api_url"), url_path);
    let response = client
        .post(url)
        .headers(construct_headers())
        .body("{}")
        .send()
        .await;
    match response {
        Ok(r) => {
            let r: serde_json::Value = r.json().await.unwrap();
            match r.get("result") {
                Some(_) => {},
                None => {},
            }
            let result: &serde_json::Value = r.get("result").unwrap();
            let first_element = result.get(0).unwrap();
            let queue_record: CvGen = serde_json::from_value(first_element.clone()).unwrap();
            let tpl_resp = get_template(queue_record);
            tpl_resp.await;
        }
        Err(e) => println!("Error: {}", e),
    }
}
这段代码工作正常,但有时当服务器返回空结果时,unwrap 会导致 panic。现在我想处理 unwrap 失败的情况,我尝试使用 match,但现在我发现使用 match 会使代码嵌套层级过多,使代码变得难看。我只想简单地处理 unwrap 失败的情况。我尝试过 unwrap_or_else,但不知道如何定义 else 条件。我应该怎么做来更好地处理这个 unwrap?
英文:
I am learning to use rust v1.65.0 to send a http request. Now I have a rust code block like this:
pub async fn get_queue_cv() {
    let client = Client::new();
    let url_path = "/cv/gen/v1/list";
    let url = format!("{}{}", get_app_config("cv.cv_api_url"), url_path);
    let response = client
        .post(url)
        .headers(construct_headers())
        .body("{}")
        .send()
        .await;
    match response {
        Ok(r) => {
            let r: serde_json::Value = r.json().await.unwrap();
            match r.get("result") {
                Some(_) => {},
                None => {},
            }
            let result: &serde_json::Value = r.get("result").unwrap();
            let first_element = result.get(0).unwrap();
            let queue_record: CvGen = serde_json::from_value(first_element.clone()).unwrap();
            let tpl_resp = get_template(queue_record);
            tpl_resp.await;
        }
        Err(e) => println!("Error: {}", e),
    }
}
This code works fine, but sometimes when the server return null results, the unwrap will going o panic. Now I want to handle the unwrap failed situation, I am tried to use match, but now I found using match make the code has too much nested level and maket the code ugly. what I want just simplely return if any of unwrap failed. I have tried unwrap_or_else but I di d not know how to define the else condition. what should I do to handle this unwrap with a better way?
答案1
得分: 1
你可以尝试使用Option的以下方法来实现"Maybe" monad的方式:
let response = r.get("result")
  .map(|x| x.get(0))
  .map(|x| serde_json::from_value(x.clone()))
  .map(|x| get_template(x));
match response {
  Some(awaiter) => awaiter.await,
  None => // TODO: your implementation
}
英文:
You can try a "Maybe" monad approach via following methods of an Option:
- https://doc.rust-lang.org/std/option/enum.Option.html#method.map
 - https://doc.rust-lang.org/std/option/enum.Option.html#method.inspect (NIGHTLY)
 
let responce = r.get("result")
  .map(|x| x.get(0))
  .map(|x| serde_json::from_value(x.clone()))
  .map(|x| get_template(x));
match responce {
  Some(awaiter) => awaiter.await
  None => // TODO: your implementation
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论