I have two methods
@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()));
}
}
On the init
method after folding i need to do more error handling but i don't like to nest too much my code. Also i don't know how to return a Failure
from the right
function.
What would be a better way to chain those values?
The cool thing about Either is, that you can chain actions and take care of error handling just once at the end. If the program fails to get the root directory, the part about creating the media subdirectories is never executed. So there is no need for nested error handling.
I am in the process of learning functional programming myself. So there might be an even better solution, but here is how I would do it:
// 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()));
}
}
You could simplify the init function even more by just returning Either instead of converting it to an Option.
Like so:
Future<Either<StorageFailure, Success>> init() async {
...
return result.flatMap(id);
}