Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid nested fold in when calling multiple Future with DartZ?

I have a piece of code that look like this:

final Either<Failure, Unit> resA = await deleteA();

resA.fold(
  (failure) => handleFailure(),
  (success) async {
    final Either<Failure, Unit> resB = await deleteB();
    resB.fold(
      (failure) => handleFailure(),
      (success) => handleSuccess(),
    );
  },
);

Basically, I want to call a first function, that returns either a Failure or a Unit (the success value doesn't matter).

Then, if the first function succeeded, I want to call another function, that also return either a Future or a Unit.

How could I do to avoid this ugly nested call of fold inside another fold?

I'm working with the package dartz, which is really cool, but lacks of documentation.

like image 873
Manu Avatar asked Apr 11 '26 15:04

Manu


1 Answers

It appears that this question has been unanswered for two years, recently I became interested in functional programming in Dart, and here I will try to answer it.

You can use traverseFuture to continue the next async process, use then to chain the future, and bind to binding the result. And finally, fold the result. And this is the code:

final Either<Failure, Unit> resA = await deleteA();
resA
  .traverseFuture((w) => deleteB())
  .then((x) => x.bind((y) => y))
  .then((z) => z.fold(
        (l) => handleFailure(l.msg),
        (r) => handleSuccess(),
      ));

The code above can be simplified again. You can directly call and chain the deleteA() without storing it into a variable, chain bind and fold in a single line, and change bind((y) => y) to bind(id) (id means identity from dartz package f(x) = x).

This is the simplified code:

deleteA()
  .then((resA) => resA.traverseFuture((w) => deleteB()))
  .then((x) => x.bind(id).fold(
        (l) => handleFailure(l.msg),
        (r) => handleSuccess(),
      ));

No ifs statement, no nested fold, just only one chaining functional statement ✨

What about the result? what about error handling? The results remain the same as what you did with double fold before, the code above (with single fold) uses the Railway Oriented Programming principle (ROP), illustrated below

ROP

So if deleteA fails, deleteB will not be executed.

And this is the error handling demo and result output:

demo

Hopefully it can solve your problem, Thanks 😉

like image 180
Adan Avatar answered Apr 13 '26 04:04

Adan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!