【发布时间】:2014-02-27 22:34:18
【问题描述】:
Dart 允许chaining futures 在不嵌套回调的情况下按顺序调用多个异步方法,这很棒。
假设我们要先连接到像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");
}
四种异步方法,但代码相当容易阅读和理解。看起来这些步骤几乎是同步和按顺序执行的。美丽的! (想象一下必须使用嵌套的 JavaScript 回调编写相同的代码......)
不幸的是,这完全行不通:我们从.connect 方法获得的RedisClient 仅分配给一个局部变量,该变量不在后续.thens 的范围内。所以,redisClient.smembers 和redisClient.get 实际上会抛出一个空指针异常。
显而易见的解决方法是将返回值保存在另一个具有函数作用域的变量中:
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 表达式,添加一对花括号和一个 @987654329 @ 语句和另一个分号。
既然这似乎是一种常见的模式,有没有更优雅的方式来做到这一点?有什么方法可以访问更下游的那些早期中间体?
【问题讨论】:
标签: dart dart-async