kitak blog

Kみたいなエンジニアになりたいブログ

タイプセーフに Future.wait したい

最近、お仕事で Dart を書いている。Dart では非同期処理を JavaScript の Promise に似た Future という概念で扱うことができて、複数の非同期処理を扱うには、JavaScript の Promise.all と同等な Future.wait という API が用意されている。

Future.wait の引数の配列の Future の型が同じ場合は問題ないが、異なる場合は共通の基底クラスにキャストされて型情報が失われてしまう(TypeScript の Promise.all でも同じはず)。

例えば、以下のようなコードで、callFooFuture<Foo>, callBarFuture<Bar>を返すとすると、results の推論された型は List<Object> になる(FooBarが共通の親を持っている場合はObjectではなく、その親になる)。

final results = await Future.wait([callFoo(), callBar()]);

こんなかんじでダウンキャストすればいいんだけど、Future オブジェクトの数が増えてくるとうっかり間違えて実行時エラーを起こしてしまいそう。

final foo = results[0] as Foo;
final bar = results[1] as Bar;

いまいまは、await しているスコープであらかじめ変数を宣言しておいて、各 Future オブジェクトの then で代入するのがいいかなぁ、と思っている。Future.all を await した結果は使わず、ただ待つだけ。

Foo foo;
Bar bar;

await Future.wait([
  callFoo().then((f) { foo = f; }),
  callBar().then((b) { bar = b; }),
]);