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()); } }