Skip to content

Commit 9fe4c64

Browse files
authored
add finallyDo to helper functions (#34)
1 parent 5f1ec87 commit 9fe4c64

File tree

2 files changed

+66
-2
lines changed

2 files changed

+66
-2
lines changed

src/ConcurrentTask.elm

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module ConcurrentTask exposing
55
, onResponseDecoderFailure, onJsException
66
, mapError, onError
77
, succeed, fail, andThen
8-
, fromResult, toResult, andThenDo, return, debug
8+
, fromResult, toResult, andThenDo, finallyDo, return, debug
99
, race
1010
, batch, sequence
1111
, map, andMap, map2, map3, map4, map5
@@ -69,7 +69,7 @@ Lift `UnexpectedError`s into regular task flow.
6969
7070
These are some general helpers that can make chaining, combining and debugging tasks more convenient.
7171
72-
@docs fromResult, toResult, andThenDo, return, debug
72+
@docs fromResult, toResult, andThenDo, finallyDo, return, debug
7373
7474
7575
# Racing Helpers
@@ -696,6 +696,40 @@ andThenDo t2 t1 =
696696
t1 |> andThen (\_ -> t2)
697697

698698

699+
{-| Always executes the Task, regardless of whether the previous Task has succeeded or failed.
700+
701+
The behavior is similar to JavaScript's `finally` block in a `try-catch-finally` statement.
702+
703+
This can, for example, be used to ensure that a resource is always released after being locked:
704+
705+
import ConcurrentTask exposing (ConcurrentTask)
706+
707+
lockResource : ConcurrentTask String ()
708+
lockResource =
709+
succeed ()
710+
711+
unlockResource : ConcurrentTask String ()
712+
unlockResource =
713+
succeed ()
714+
715+
performOperation : ConcurrentTask String ()
716+
performOperation =
717+
fail "operation failed"
718+
719+
secureOperation : ConcurrentTask String ()
720+
secureOperation =
721+
lockResource
722+
|> andThenDo performOperation
723+
|> finallyDo unlockResource
724+
725+
-}
726+
finallyDo : ConcurrentTask x a -> ConcurrentTask x b -> ConcurrentTask x a
727+
finallyDo t2 t1 =
728+
t1
729+
|> onError (\e -> t2 |> andThenDo (fail e))
730+
|> andThenDo t2
731+
732+
699733
{-| Succeed with a hardcoded value after the previous Task.
700734
701735
Maybe you want to do some Tasks on a User but allow it to be chained onwards:

tests/TaskTest.elm

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ suite =
2323
[ hardcoded
2424
, successResponses
2525
, errors
26+
, helpers
2627
]
2728

2829

@@ -448,6 +449,35 @@ hardcoded =
448449
]
449450

450451

452+
helpers : Test
453+
helpers =
454+
describe "Task Helpers"
455+
[ describe "finallyDo"
456+
[ test "Runs the followup task when the first task succeeds" <|
457+
\_ ->
458+
createTask
459+
|> ConcurrentTask.finallyDo createTask
460+
|> runTask
461+
[ ( 0, Encode.string "first" )
462+
, ( 1, Encode.string "followup" )
463+
]
464+
|> Expect.equal (Internal.Success "followup")
465+
, test "Runs the followup task when the first task fails" <|
466+
\_ ->
467+
createTask
468+
|> ConcurrentTask.finallyDo (ConcurrentTask.succeed "followup")
469+
|> evalTask
470+
[ ( 0, jsException "error" Encode.null )
471+
, ( 1, Encode.string "followup" )
472+
]
473+
|> Expect.all
474+
[ Tuple.second >> Expect.equal (Internal.Error "error")
475+
, Tuple.first >> Ids.get >> Expect.equal "1"
476+
]
477+
]
478+
]
479+
480+
451481

452482
-- Task Runner
453483

0 commit comments

Comments
 (0)