Dart允许链接期货按顺序调用多个异步方法而不嵌套回调,这很棒.
假设我们想首先连接到像Redis这样的数据存储,然后运行一堆顺序读取:
Future FirstValue(String indexKey)
{
return RedisClient.connect(Config.connectionStringRedis)
.then((RedisClient redisClient) => redisClient.exists(indexKey))
.then((bool exists) => !exists ? null : redisClient.smembers(indexKey))
.then((Set keys) => redisClient.get(keys.first))
.then((String value) => "result: $value");
}
四种异步方法,但代码相当容易阅读和理解.几乎看起来步骤是同步并按顺序执行的.美丽!(想象一下,必须使用嵌套的JavaScript回调编写相同的代码......)
不幸的是,这不会很有效:我们从.connect
方法中获得的RedisClient 仅被分配给一个局部变量,该变量不在后续.then
s的范围内.所以,redisClient.smembers
和redisClient.get
实际上将抛出一个空指针异常.
显而易见的解决方法是将返回值保存在具有函数范围的另一个变量中:
Future 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 keys) => redisClient.get(keys.first))
.then((String value) => "result: $value");
}
不幸的是,这使得代码更详细和更小美:现在有一个额外的辅助变量(theRedisClient),我们不得不更换一个匿名函数的Lambda表达式之一,再配上一双大括号和一个return
声明和其他分号.
由于这似乎是一种常见的模式,有没有更优雅的方式来做到这一点?有没有办法进一步访问链中的那些早期中间体?