Cancellable futures for ReScript
Run the following in your console:
$ yarn add rescript-futureThen add rescript-future to your rescript.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(Console.log)
// Logs: 3See 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: Executescbwithfuture'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) => boolisCancelled(future) => boolisResolved(future) => bool
mapResult(future, mapper)mapOk(future, mapper)flatMapOk(future, mapper)mapError(future, mapper)flatMapError(future, mapper)
tap(future, cb) => futuretapOk(resultFuture, cb) => resultFuturetapError(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.fromPromiseFuturePromise.toPromiseFuturePromise.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 pendingHeavily inspired by RationalJS/future's API