$ cat learning-effect-10-concurrency-without-guessing.md
Part 10: Concurrency Without Guessing
$ tail -f learning-effect-10-concurrency-without-guessing/readers
connecting…
At some point, a program needs two things that do not depend on each other.
Fetch the user.
Fetch the invoices.
Those can run at the same time.
Run both
const program = Effect.all({ user: fetchUser(userId), invoices: fetchInvoices(userId),});This gives one Effect with both results.
Effect.Effect< { user: User; invoices: Invoice[] }, UserNotFound | InvoiceApiDown, UserRepo | InvoiceClient>;That type is doing useful work.
It shows the combined success, combined errors, and combined requirements.
Parallel when it is safe
Some work must be sequential.
You cannot fetch invoices for a user id before you have parsed the user id.
But once you have the id, independent calls can run together.
const program = parseUserId(input).pipe( Effect.flatMap((userId) => Effect.all({ user: fetchUser(userId), invoices: fetchInvoices(userId), }), ),);The nice part
In normal async code, I often have to inspect the Promise.all shape and then think about errors separately.
Effect keeps the shape together.
Success. Error. Requirements.
The same three slots again.