1

我有两种方法

@override
  Future<Option<StorageFailure>> init() async {
    final root = await getRootDir();
    return root.fold(
      (failure) => some(failure),
      (dir) {
        final images = Directory("$dir/images");
        final videos = Directory("$dir/videos");
        images.create(); // more error handling here (try|either)
        videos.create();
      },
    );
  }

  @override
  Future<Either<StorageFailure, Directory>> getRootDir() async {
    try {
      final root = await getApplicationDocumentsDirectory();
      return right(Directory("${root.path}/files"));
    } catch (e) {
      return left(StorageFailure(reason: e.toString()));
    }
  }

在折叠后的init方法上,我需要做更多的错误处理,但我不喜欢嵌套太多我的代码。我也不知道如何Failureright函数中返回 a 。

链接这些价值观的更好方法是什么?

4

1 回答 1

1

Either 最酷的地方在于,您可以链接操作并在最后只处理一次错误。如果程序无法获取根目录,则永远不会执行有关创建媒体子目录的部分。所以不需要嵌套错误处理。

我自己也在学习函数式编程。所以可能有一个更好的解决方案,但我会这样做:

// I intentionally added all type annotations for better understanding.
Future<Option<StorageFailure>> init() async {
  final Either<StorageFailure, Directory> root = await getRootDir();
  final Either<StorageFailure, Either<StorageFailure, Success>> result = await root.traverseFuture(createImagesAndVideosSubfolders);
  final Either<StorageFailure, Success> flattenedResult = result.flatMap(id);
  return flattenedResult.fold((failure) => some(failure), (success) => none());
}

Future<Either<StorageFailure, Success>> createImagesAndVideosSubfolders(Directory dir) async {
  try {
    await Directory('${dir.path}/images').create();
    await Directory('${dir.path}/videos').create();
    return right(Success('success'));
  } catch (e) {
    return left(StorageFailure(reason: e.toString()));
  }
}
  1. 获取根目录
  2. 创建媒体目录(如果 getRootDir 失败,root.traverseFuture 方法只返回现有的 StorageFailure)
  3. 使用 flatMap 和 id 函数展平嵌套的 Eithers。traverseFuture 方法是期货的地图版本。如果future 也有一个flatMap 等价物,则结果将不会被包装在一个或中,并且不需要最后一步来展平结果。

您可以通过仅返回 Either 而不是将其转换为 Option 来进一步简化 init 函数。

像这样:

Future<Either<StorageFailure, Success>> init() async {
  ...
  return result.flatMap(id);
}
于 2020-06-28T15:47:34.733 回答