Dart では、Future を連鎖させて、コールバックをネストすることなく、複数の非同期メソッドを順番に呼び出すことができます。これは素晴らしいことです。
最初にRedisのようなデータ ストアに接続し、一連の順次読み取りを実行したいとします。
Future<String> FirstValue(String indexKey)
{
return RedisClient.connect(Config.connectionStringRedis)
.then((RedisClient redisClient) => redisClient.exists(indexKey))
.then((bool exists) => !exists ? null : redisClient.smembers(indexKey))
.then((Set<String> keys) => redisClient.get(keys.first))
.then((String value) => "result: $value");
}
4 つの非同期メソッドがありますが、コードは非常に読みやすく、理解しやすいものです。ステップが同期して順番に実行されているように見えます。美しい!(ネストされた JavaScript コールバックを使用して同じコードを書かなければならないことを想像してみてください...)
残念ながら、これはうまくいきません。メソッドから取得した RedisClient は、後続の s の.connect
スコープ外のローカル変数にのみ割り当てられます。.then
そのため、redisClient.smembers
実際redisClient.get
には null ポインター例外がスローされます。
明らかな修正は、戻り値を関数スコープを持つ別の変数に保存することです。
Future<String> FirstValue(String indexKey)
{
RedisClient redisClient = null;
return RedisClient.connect(Config.connectionStringRedis)
.then((RedisClient theRedisClient)
{
redisClient = theRedisClient;
return redisClient.exists(indexKey);
})
.then((bool exists) => !exists ? null : redisClient.smembers(indexKey))
.then((Set<String> keys) => redisClient.get(keys.first))
.then((String value) => "result: $value");
}
残念ながら、これによりコードがより冗長になり、見栄えが悪くなります。追加のヘルパー変数 (theRedisClient) があり、Lambda 式の 1 つを匿名関数に置き換えて、中かっこのペアとreturn
ステートメントと別のセミコロンを追加する必要がありました。
これは一般的なパターンのように見えるので、これを行うよりエレガントな方法はありますか? チェーンのさらに下にある以前の中間にアクセスする方法はありますか?