sontixyou blog

技術まわり、ガジェット関連について

awaitとawait?について

tokio crateを使って、非同期処理を書きたい場合、ほぼほぼasync await構文を書くと思う。 私は、awaitとawait?の違い、使い分けがいまいちわからないでの、頭の整理がてら書いていく。

await

awaitは、非同期関数の結果を待つ。async関数やブロックから呼び出され、

非同期で処理が完了するまで実行を停止します。これにより、他のタスクが並行して実行されることが可能になります。

また、エラーが発生時は、自分でエラーをハンドリングする必要がある。

だが、await?より細かいエラーをハンドリングできそうな印象あるが、コード量は少し増える。

#[tokio::main]
async fn main() {
    let result = some_async_function().await;
    println!("Result: {:?}", result);
}

async fn some_async_function() -> u32 {
    42
}

いい例なのかはわからん。

use reqwest::Error;

#[tokio::main]
async fn main() -> Result<(), Option<Error>> {
    let response = make_request("https://xjsonplaceholder.typicode.com/posts/1").await?;
    println!("Response: {:?}", response);
    Ok(())
}

async fn make_request(url: &str) -> Result<String, Option<Error>> {
    let response = reqwest::get(url).await;
    match response {
        Ok(response) => {
            // レスポンスのステータスコードをチェックし、エラーハンドリング
            if response.status().is_success() {
                let body = response.text().await?;
                Ok(body)
            } else {
                // ステータスコードが成功でない場合はエラーを返す
                return Err(response.error_for_status_ref().err());
            }
        }
        Err(e) => Err(Some(e)),
    }
}

await?

非同期関数の完了を待ちつつ、Result型のエラーハンドリングも行います。

エラーが発生した場合には関数を終了し、エラーを呼び出し元に返します。

use std::error::Error;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let result = some_async_function().await?;
    println!("Result: {}", &result);
    Ok(())
}

async fn some_async_function() -> Result<u32, Box<dyn Error>> {
    Ok(42)
}

ほかの事例だとこんな例

use reqwest::Error;

#[tokio::main]
async fn main() -> Result<(), Option<Error>> {
    let response = make_request("https://xjsonplaceholder.typicode.com/posts/1").await?;
    println!("Response: {:?}", response);
    Ok(())
}

async fn make_request(url: &str) -> Result<String, Option<Error>> {
    let response = reqwest::get(url).await?;

    // レスポンスのステータスコードをチェックし、エラーハンドリング
   // ここでresponseがエラーかを判断するにはstatusコードを確認する。
    if response.status().is_success() {
        let body = response.text().await?;
        Ok(body)
    } else {
        // ステータスコードが成功でない場合はエラーを返す
        return Err(response.error_for_status_ref().err());
    }
}