链接飞镖未来 - 可能获得中间结果?

Max*_*Max 8 dart dart-async

Dart允许链接期货按顺序调用多个异步方法而不嵌套回调,这很棒.

假设我们想首先连接到像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");
  }
Run Code Online (Sandbox Code Playgroud)

四种异步方法,但代码相当容易阅读和理解.几乎看起来步骤是同步并按顺序执行的.美丽!(想象一下,必须使用嵌套的JavaScript回调编写相同的代码......)

不幸的是,这不会有效:我们从.connect方法中获得的RedisClient 仅被分配给一个局部变量,该变量不在后续.thens的范围内.所以,redisClient.smembersredisClient.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");    
  }
Run Code Online (Sandbox Code Playgroud)

不幸的是,这使得代码更详细和更小美:现在有一个额外的辅助变量(theRedisClient),我们不得不更换一个匿名函数的Lambda表达式之一,再配上一双大括号和一个return声明和其他分号.

由于这似乎是一种常见的模式,有没有更优雅的方式来做到这一点?有没有办法进一步访问链中的那些早期中间体?

Ale*_*uin 6

您可以使用嵌套赋值来避免花括号和return:

.then((RedisClient rc) => (redisClient = rc).exists(indexKey))
Run Code Online (Sandbox Code Playgroud)