【问题标题】:Where should I put completer.complete() in this series of Future functions?在这一系列的 Future 函数中,我应该把 completer.complete() 放在哪里?
【发布时间】:2015-02-23 15:52:53
【问题描述】:

我的函数必须创建一个目录,并将整个文件夹层次结构从另一个目录复制到这个新目录。所有的操作都是异步完成的,但是我希望这个函数返回一个 Future,当我在它上面调用 .then(result) 时,它将完成所有的异步工作。

但我不知道我应该把我的completer.complete() 放在哪里来实现这一点。

Future<Directory> createCopyDirectory(Directory directoryToCreate){
  Completer<Directory> completer = new Completer<Directory>();
  completer.complete(
      directoryToCreate.create().then((directory){
        Directory contentToCopy = new Directory(globalPathOfDirectoryToCopy);
        List<Future> creatingContent = new List<Future>();
        contentToCopy.list(recursive:true, followLinks:false).forEach((f){
          if (f is File){
            File fileToCreate = new File(f.path.replaceFirst('pages', userID));
            creatingContent.add(fileToCreate.create(recursive:true).then((_){
              f.readAsString().then((fileContent){
                fileToCreate.writeAsString(fileContent);
              });
            }));
          }
        });
        return Future.wait(creatingContent).then((_){ return directoryToCreate;});
    })
  );
  return completer.future;
}

我确切地说我的函数按预期工作,但是如果我尝试直接访问我应该在这个函数中创建的内容,就像在then() 调用中一样,Dart 给我带来了一个期望,就像我没有创建内容一样。所以completer.complete() 肯定是错误的,在内容创建之前调用then()

我尝试在结尾处使用completer.complete() Future.wait(creatingContent) 或将return directoryToCreate 替换为completer.complete(directoryToCreate),但结果是一样的。

我对在这种情况下构建适当的基于 Future 的函数的方式有点困惑。

【问题讨论】:

    标签: dart future dart-async


    【解决方案1】:

    你不应该在这里需要Completer

    Future<Directory> createCopyDirectory(Directory directoryToCreate) {
      return directoryToCreate.create().then((directory) {
        String userID = split(userDirectory.path).last;
        Directory contentToCopy = new Directory(globalPathOfDirectoryToCopy);
        List<Future> creatingContent = new List<Future>();
        return contentToCopy
            .list(recursive: true, followLinks: false)
            .forEach((File f) {
          if (f is File) {
            File fileToCreate = new File(f.path.replaceFirst('pages', userID));
            creatingContent.add(fileToCreate.create(recursive: true).then((_) {
              return f.readAsString().then((fileContent) {
                return fileToCreate.writeAsString(fileContent);
              });
            }));
          }
        }).then((_) {
          return Future.wait(creatingContent).then((_) {
            return directoryToCreate;
          });
        });
      });
    }
    

    只是为了演示如何使用Completer

    Future<Directory> createCopyDirectory(Directory directoryToCreate) {
      Completer<Directory> completer = new Completer<Directory>();
      directoryToCreate.create().then((directory) {
        String userID = split(userDirectory.path).last;
        Directory contentToCopy = new Directory(globalPathOfDirectoryToCopy);
        List<Future> creatingContent = new List<Future>();
        contentToCopy.list(recursive: true, followLinks: false).forEach((f) {
          if (f is File) {
            File fileToCreate = new File(f.path.replaceFirst('pages', userID));
            creatingContent.add(fileToCreate.create(recursive: true).then((_) {
              return f.readAsString().then((fileContent) {
                return fileToCreate.writeAsString(fileContent);
              });
            }));
          }
        }).then((_) => Future
            .wait(creatingContent)
            .then((_) => completer.complete(directoryToCreate)));
      });
      return completer.future;
    }
    

    【讨论】:

    • 我更新了我的答案(仅第一部分)。在contentToCopy 之前添加一个return,在foreEach 末尾添加一个.then(...
    • 当你评论它时,我发现它是正确的。非常感谢您的脑力劳动,它激励我更有活力地发现问题。
    • 我很喜欢。这是一个相当高级的异步示例,我自己也学到了一些新东西:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-30
    • 2014-02-27
    • 2016-08-25
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多