future
gleam add future@1
Usage
Creating a future
import future
pub fn to_run(x: Int) -> Result(Int, Nil) {
Ok(x + x)
}
pub fn main() {
/// To create a future you must provide a function that takes a single argument and returns a Result
/// The first argument is the argument passed to the future
/// Nil is valid as an argument an as wrapped by the returned Result
let fut = future.new(to_run, 1)
case future.status(fut) {
/// The future is still running
future.Running -> todo
/// The future has completed and returned a result
future.Completed(result) ->
case result {
/// We can now access the result of the future
Ok(x) -> todo
/// The functon doesn't ever return an error so we can just add a guard
Error(x) -> panic as "An error occured!"
}
/// Failures are triggered by two things:
/// - An external exception was thrown
/// - Gleam called a panic
/// If an external exception was thrown then the reason will be a stringified version of the exception
/// If Gleam called a panic then the reason will be the message passed to the panic
future.Failed(reason) -> panic as reason
/// The future is no longer in memory and it's status cannot be used
future.Released -> panic as "The future has been released"
}
{
use value <- future.then(fut)
/// The future has been completed and the result is available
/// We can now access the result of the future
/// This will return a new future that won't start executing until the prior future has completed
todo
}
{
use message <- future.add_failure_handler(fut)
/// The future has failed for the provided reason
/// We can now access the reason for the failure
/// This will return nothing
todo
}
{
use state <- future.after(fut)
/// The future has completed and a final status is available
/// This will return nothing
todo
}
/// You should always release the future when you are done with it as erlang will keep it in memory forever otherwise
/// If you don't want to manually release memory look towards `auto_release`, it releases the future as soon as it's complete. This still allows for chaining futures with `then` (assuming the prior future doesn't exit immediately) but ensures the future is released as soon as possible.
fut |> future.release
}
Resolving a future immediately
import future
pub fn main() {
/// The result will be immediately available via status
/// It will also never be marked as running
let fut = future.from_result(Ok(1)) // This can be an Error too!
/// Do still make sure to release the future
fut |> future.release
}
import future
pub fn main() {
/// The failure message will be immediately available via status
/// It will also never be marked as running
let fut = future.from_failure("example")
/// Do still make sure to release the future
fut |> future.release
}
Manually controlling a future
import future
import future/manual
pub fn main() {
/// Create a future that only completes when you call a function
let #(resolve, reject, fail, fut) = manual.new()
/// Only the first function to be called will be the result of the future
/// Any further calls will be ignored
resolve("hi") // Will complete the future with Ok("hi")
reject("bye") // Will complete the future with Error("bye")
fail("oh no") // Will fail the future with Failed("oh no")
/// Release the future when you are done with it
fut |> future.release
}
Using a delay
import future
import future/delay
pub fn main() {
/// Creates a future that resolves after the provided duration
/// This is designed for use with `after` or `then` to delay the execution of some code
let fut = delay.of(1000)
/// Do still make sure to release the future
fut |> future.release
}
Supported runtimes
Runtime | Supported |
---|---|
Erlang | ✅ |
Node | ✅ |
Deno | ✅ |
Bun | ✅ |
Contributing
PRs are welcome with or without prior discussion.
License
This project is licensed under the Apache License, Version 2.0.
See LICENSE for more information.
Additional information
If you’re unsure about anything, contact me directly via BradBot_1#2042
Further documentation can be found at https://hexdocs.pm/future.