Cancellable futures for ReScript
Run the following in your console:
$ yarn add rescript-future
Then add rescript-future
to your bsconfig.json
's bs-dependencies
:
{
"bs-dependencies": [
+ "rescript-future"
]
}
A Future is a data structure that represents a potential value. It works both synchronously & asynchrously. It consists of 3 possible states:
Pending
: The value is yet to be resolvedCancelled
: The future has been cancelled before could resolveResolved
: The future holds its value
// Basic synchronous future
Future.value(1)
->Future.map(x => x + 1)
->Future.flatMap(x => Future.value(x + 1))
->Future.get(Js.log)
// Logs: 3
See the details in the interface file
value('a) => Future.t<'a>
: creates a resolved futuremakePure(('a => unit) => unit) => Future.t<'a>
: creates a futuremake(('a => unit) => option<unit => unit>) => Future.t<'a>
: creates a future with a cancellation effect
cancel(future)
: Cancels a future and its dependents
get(future, cb) => unit
: Executescb
withfuture
's resolved value
map(future, mapper)
: Returns a new mapped futureflatMap(future, mapper)
: Returns a new mapped future with mapper returning a future itself
isPending(future) => bool
isCancelled(future) => bool
isResolved(future) => bool
mapResult(future, mapper)
mapOk(future, mapper)
flatMapOk(future, mapper)
mapError(future, mapper)
flatMapError(future, mapper)
tap(future, cb) => future
tapOk(resultFuture, cb) => resultFuture
tapError(resultFuture, cb) => resultFuture
all2((future, future))
all3((future, future, future))
all4((future, future, future, future))
all5((future, future, future, future, future))
all6((future, future, future, future, future, future))
all(array<future>)
FuturePromise.fromPromise
FuturePromise.toPromise
FuturePromise.resultToPromise
In JavaScript, Promises
are not cancellable. That can be limiting at times, especially when using React
's useEffect
, that let's you return a cancellation effect in order to prevent unwanted side-effects.
let valueFromServer = Future.make(resolve => {
let request = getFromServer((err, data) => {
if err {
resolve(Error(err))
} else {
resolve(Ok(data))
}
})
Some(() => cancelRequest(request))
})
let deserializedValueFromServer =
valueFromServer->Future.map(deserialize)
Future.cancel(valueFromServer)
// valueFromServer & deserializedValueFromServer are cancelled if they were still pending
Heavily inspired by RationalJS/future's API