wasm-bindgen で fetch する rustwasm 公式の example の async で JsFuture な run が実行時に失敗した場合にも安全に対応できるようにする方法のメモ
問題
↑
- この example の
run
にrustwasm/wasm-bindgen
のような、実装上GitHub APIで取得可能なポジトリーが実在する場合は問題ありません。 - リポジトリーが存在しないパターンを
run
に与えてfetch
させるとasync
/JsFuture
処理系の都合か二度とrun
を使用できない .wasm が生成されてしまいます。
問題は example の run
の最後の2行:
// Use serde to parse the JSON into a struct. let branch_info: Branch = json.into_serde().unwrap(); // Send the `Branch` struct back to JS as an `Object`. Ok(JsValue::from_serde(&branch_info).unwrap())
解決方法
match
で json
の Err<serde_json::error::Error>
を Err<JsValue>
に射る:
// 解決方法①段階 match json.into_serde() as Result<Branch, serde_json::error::Error> { Ok(branch_info) => Ok(JsValue::from_serde(&branch_info).unwrap()), Err(e) => Err(JsValue::from_str(&format!("{}", e))), }
↑だとまだ json.into_serde()
は Ok
だけど JsValue::from_serde
が Err
だった場合は死んでしまいますが、 GitHub API は実在しないリポジトリーに対しても JSON を返してはくれるので、さしあたりは問題にはなりません。そこも match
すると↓:
// 解決方法②段階 match json.into_serde() as Result<Branch, serde_json::error::Error> { Ok(branch_info) => match JsValue::from_serde(&branch_info) { Ok(jsvalue) => Ok(jsvalue), Err(e) => Err(JsValue::from_str(&format!("{}", e))), }, Err(e) => Err(JsValue::from_str(&format!("{}", e))), }
↑のそこはかとない多段 match
のダサさを Result
の map
と map_err
で整理すると:
// 解決方法③段階 (json.into_serde() as Result<Branch, serde_json::error::Error>) .map(|branch_info| JsValue::from_serde(&branch_info).unwrap()) .map_err(|e| JsValue::from_str(&format!("{}", e)))
- (1.
json.into_serde()
):json.into_serde()
:=Ok<Branch>
かErr<serde_json::error::Error>
です - (2.
map
): (a) がOk
の場合にmap
でfrom_serde
の結果をunwrap
:=Ok<JsValue>
またはErr<serde_json::error::Error>
です - (3.
map_err
): (a) または (b) の何れかがErr<serde_json::error::Error>
の場合はmap_err
でErr<JsValue>
に変換されます
こうすると run
の内部で Err<serde_json::error::Error> が発生しても Uncaught (in promise) missing filed `name` at line 1 column 104
のような console.error
が吐かれるだけで、 run
が使用不能には至らなくなります。
この他にも unwrap()
により panic が発生する可能性がある部分はありますが、 GitHub が 404 になったり JSON レスポンスを廃止しない限りは事実上死には至らないです。学習用途ではなく実用する場合はより厳密に async
/JsFuture
の絡む内部で panic が発生しないように気にする必要はあります。