Deferred
One-time coordination cells for Effect programs. A Deferred<A, E> starts
empty, can be completed exactly once with a success, failure, defect, or
interruption, and lets any number of fibers wait for that result. Awaiting a
Deferred suspends the fiber instead of blocking an operating-system thread,
and every waiter observes the same completion.
Completion
Runs the supplied Effect and attempts to complete the Deferred with its
memoized result.
When to use
Use when completing a Deferred should run an effect once and share its
result with all awaiters.
Details
The returned effect succeeds with true when this call completed the
Deferred, or false if it was already completed.
See
- completeWith for storing an effect directly without memoizing its result
Signature
declare const complete: { <A, E, R>(effect: Effect<A, E, R>): (self: Deferred<A, E>) => Effect<boolean, never, R>; <A, E, R>(self: Deferred<A, E>, effect: Effect<A, E, R>): Effect<boolean, never, R>;}Example
(Completing a Deferred from an effect)
import { Deferred, Effect } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number>() const completed = yield* Deferred.complete(deferred, Effect.succeed(42)) const value = yield* Deferred.await(deferred) return [completed, value]})
await Effect.runPromise(program) // => [true, 42]completeWith
Attempts to complete the Deferred with the specified effect directly.
When to use
Use to store an already environment-free effect as the completion without running it during completion.
Details
The returned effect succeeds with true when this call completed the
Deferred, or false if it was already completed.
Gotchas
The supplied effect is not memoized by completeWith; each awaiter may run
the stored effect independently.
See
Signature
declare const completeWith: { <A, E>(effect: Effect<A, E>): (self: Deferred<A, E>) => Effect<boolean>; <A, E>(self: Deferred<A, E>, effect: Effect<A, E>): Effect<boolean>;}Example
(Completing a Deferred with an effect)
import { Deferred, Effect } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number>() const completed = yield* Deferred.completeWith(deferred, Effect.succeed(42)) const value = yield* Deferred.await(deferred) return [completed, value]})
await Effect.runPromise(program) // => [true, 42]Attempts to complete the Deferred with a defect.
When to use
Use to complete a Deferred with an unexpected defect.
Details
Fibers waiting on the Deferred die with that defect only if this call
completes it. The returned effect succeeds with true when this call
completed the Deferred, or false if it was already completed.
Signature
declare const die: { (defect: unknown): <A, E>(self: Deferred<A, E>) => Effect<boolean>; <A, E>(self: Deferred<A, E>, defect: unknown): Effect<boolean>;}Example
(Killing a Deferred with a defect)
import { Deferred, Effect, Exit } from "effect"
const defect = new Error("Something went wrong")const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number>() const success = yield* Deferred.die(deferred, defect) const exit = yield* Effect.exit(Deferred.await(deferred)) return [success, exit]})
await Effect.runPromise(program) // => [true, Exit.die(defect)]Computes a defect when the returned effect is run, then attempts to complete
the Deferred with that defect.
When to use
Use to lazily compute an unexpected defect when the completion effect runs.
Details
Fibers waiting on the Deferred die with the computed defect only if this
call completes it. The returned effect succeeds with true when this call
completed the Deferred, or false if it was already completed.
Signature
declare const dieSync: { (evaluate: LazyArg<unknown>): <A, E>(self: Deferred<A, E>) => Effect<boolean>; <A, E>(self: Deferred<A, E>, evaluate: LazyArg<unknown>): Effect<boolean>;}Example
(Killing a Deferred with a lazy defect)
import { Deferred, Effect, Exit } from "effect"
const defect = new Error("Lazy error")const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number>() const success = yield* Deferred.dieSync(deferred, () => defect) const exit = yield* Effect.exit(Deferred.await(deferred)) return [success, exit]})
await Effect.runPromise(program) // => [true, Exit.die(defect)]Completes the Deferred with the specified Exit value, which will be
propagated to all fibers waiting on the value of the Deferred.
When to use
Use to complete a Deferred from an already computed Exit.
Details
The returned effect succeeds with true when this call completed the
Deferred, or false if it was already completed.
See
- complete for completing from an effect and memoizing its result
- completeWith for storing an effect directly
- succeed for completing with a success value
- failCause for completing with a failure cause
Signature
declare const done: { <A, E>(exit: Exit<A, E>): (self: Deferred<A, E>) => Effect<boolean>; <A, E>(self: Deferred<A, E>, exit: Exit<A, E>): Effect<boolean>;}Example
(Completing a Deferred with an Exit)
import { Deferred, Effect, Exit } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number>() yield* Deferred.done(deferred, Exit.succeed(42)) return yield* Effect.exit(Deferred.await(deferred))})
await Effect.runPromise(program) // => Exit.succeed(42)Attempts to complete the Deferred with the specified error.
When to use
Use to complete a Deferred with a typed failure value.
Details
Fibers waiting on the Deferred fail with that error only if this call
completes it. The returned effect succeeds with true when this call
completed the Deferred, or false if it was already completed.
Signature
declare const fail: { <E>(error: E): <A>(self: Deferred<A, E>) => Effect<boolean>; <A, E>(self: Deferred<A, E>, error: E): Effect<boolean>;}Example
(Failing a Deferred with an error)
import { Deferred, Effect, Exit } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number, string>() const success = yield* Deferred.fail(deferred, "Operation failed") const exit = yield* Effect.exit(Deferred.await(deferred)) return [success, exit]})
await Effect.runPromise(program) // => [true, Exit.fail("Operation failed")]Attempts to complete the Deferred with the specified Cause.
When to use
Use to complete a Deferred with a full failure cause.
Details
Fibers waiting on the Deferred observe that cause only if this call
completes it. The returned effect succeeds with true when this call
completed the Deferred, or false if it was already completed.
Signature
declare const failCause: { <E>(cause: Cause<E>): <A>(self: Deferred<A, E>) => Effect<boolean>; <A, E>(self: Deferred<A, E>, cause: Cause<E>): Effect<boolean>;}Example
(Failing a Deferred with a Cause)
import { Cause, Deferred, Effect, Exit } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number, string>() const success = yield* Deferred.failCause(deferred, Cause.fail("Operation failed")) const exit = yield* Effect.exit(Deferred.await(deferred)) return [success, exit]})
await Effect.runPromise(program) // => [true, Exit.failCause(Cause.fail("Operation failed"))]failCauseSync
Computes a Cause when the returned effect is run, then attempts to
complete the Deferred with that cause.
When to use
Use to lazily compute a full failure cause when the Deferred completion
effect runs.
Details
Fibers waiting on the Deferred observe the computed cause only if this
call completes it. The returned effect succeeds with true when this call
completed the Deferred, or false if it was already completed.
Signature
declare const failCauseSync: { <E>(evaluate: LazyArg<Cause<E>>): <A>(self: Deferred<A, E>) => Effect<boolean>; <A, E>(self: Deferred<A, E>, evaluate: LazyArg<Cause<E>>): Effect<boolean>;}Example
(Failing a Deferred with a lazy Cause)
import { Cause, Deferred, Effect, Exit } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number, string>() const success = yield* Deferred.failCauseSync(deferred, () => Cause.fail("Lazy error")) const exit = yield* Effect.exit(Deferred.await(deferred)) return [success, exit]})
await Effect.runPromise(program) // => [true, Exit.failCause(Cause.fail("Lazy error"))]Computes an error when the returned effect is run, then attempts to complete
the Deferred with that error.
When to use
Use to lazily compute a typed failure value when the Deferred completion
effect runs.
Details
Fibers waiting on the Deferred fail with the computed error only if this
call completes it. The returned effect succeeds with true when this call
completed the Deferred, or false if it was already completed.
Signature
declare const failSync: { <E>(evaluate: LazyArg<E>): <A>(self: Deferred<A, E>) => Effect<boolean>; <A, E>(self: Deferred<A, E>, evaluate: LazyArg<E>): Effect<boolean>;}Example
(Failing a Deferred with a lazy error)
import { Deferred, Effect, Exit } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number, string>() const success = yield* Deferred.failSync(deferred, () => "Lazy error") const exit = yield* Effect.exit(Deferred.await(deferred)) return [success, exit]})
await Effect.runPromise(program) // => [true, Exit.fail("Lazy error")]Attempts to complete the Deferred with interruption by the current fiber.
When to use
Use to complete a Deferred as interrupted by the current fiber.
Details
Fibers waiting on the Deferred are interrupted with the current fiber id
only if this call completes it. The returned effect succeeds with true
when this call completed the Deferred, or false if it was already
completed.
Signature
declare function interrupt<A, E>(self: Deferred<A, E>): Effect<boolean>Example
(Interrupting a Deferred)
import { Deferred, Effect, Exit } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number>() const success = yield* Deferred.interrupt(deferred) const exit = yield* Effect.exit(Deferred.await(deferred)) return [success, exit] as const})
const [success, exit] = await Effect.runPromise(program)success // => trueExit.hasInterrupts(exit) // => trueinterruptWith
Attempts to complete the Deferred with interruption by the specified
FiberId.
When to use
Use to complete a Deferred as interrupted by a specific fiber id.
Details
Fibers waiting on the Deferred are interrupted with that fiber id only if
this call completes it. The returned effect succeeds with true when this
call completed the Deferred, or false if it was already completed.
Signature
declare const interruptWith: { (fiberId: number): <A, E>(self: Deferred<A, E>) => Effect<boolean>; <A, E>(self: Deferred<A, E>, fiberId: number): Effect<boolean>;}Example
(Interrupting a Deferred with a fiber id)
import { Deferred, Effect, Exit } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number>() const success = yield* Deferred.interruptWith(deferred, 42) const exit = yield* Effect.exit(Deferred.await(deferred)) return [success, exit]})
await Effect.runPromise(program) // => [true, Exit.interrupt(42)]Runs an Effect and attempts to complete a Deferred with the effect's
result.
When to use
Use to pipe an effect result into a Deferred while preserving success,
failure, defects, and interruption.
Details
If the effect succeeds, fails, dies, or is interrupted, that result is used
as the attempted completion. The returned effect cannot fail; it succeeds
with true if it completed the Deferred, or false if the Deferred was
already completed.
Signature
declare const into: { <A, E>(deferred: Deferred<A, E>): <R>(self: Effect<A, E, R>) => Effect<boolean, never, R>; <A, E, R>(self: Effect<A, E, R>, deferred: Deferred<A, E>): Effect<boolean, never, R>;}Example
(Completing a Deferred from an effect result)
import { Deferred, Effect } from "effect"
const successEffect = Effect.succeed(42)
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number, string>() const isCompleted = yield* Deferred.into(successEffect, deferred) const value = yield* Deferred.await(deferred) return [isCompleted, value]})
await Effect.runPromise(program) // => [true, 42]Attempts to complete the Deferred with the specified value.
When to use
Use to complete a Deferred with a successful value.
Details
Fibers waiting on the Deferred receive the value only if this call
completes it. The returned effect succeeds with true when this call
completed the Deferred, or false if it was already completed.
Signature
declare const succeed: { <A>(value: A): <E>(self: Deferred<A, E>) => Effect<boolean>; <A, E>(self: Deferred<A, E>, value: A): Effect<boolean>;}Example
(Completing a Deferred with a value)
import { Deferred, Effect } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number>() yield* Deferred.succeed(deferred, 42)
return yield* Deferred.await(deferred)})
await Effect.runPromise(program) // => 42Computes a value when the returned effect is run, then attempts to complete
the Deferred with that value.
When to use
Use to lazily compute a successful value when the Deferred completion
effect runs.
Details
Fibers waiting on the Deferred receive the computed value only if this call
completes it. The returned effect succeeds with true when this call
completed the Deferred, or false if it was already completed.
Signature
declare const sync: { <A>(evaluate: LazyArg<A>): <E>(self: Deferred<A, E>) => Effect<boolean>; <A, E>(self: Deferred<A, E>, evaluate: LazyArg<A>): Effect<boolean>;}Example
(Completing a Deferred with a lazy value)
import { Deferred, Effect } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number>() yield* Deferred.sync(deferred, () => 42) return yield* Deferred.await(deferred)})
await Effect.runPromise(program) // => 42Constructors
Creates a new Deferred.
When to use
Use to allocate an empty Deferred inside an Effect workflow.
Signature
declare function make<A, E = never>(): Effect<Deferred<A, E>>Example
(Creating a Deferred)
import { Deferred, Effect } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number>() yield* Deferred.succeed(deferred, 42) return yield* Deferred.await(deferred)})
await Effect.runPromise(program) // => 42Getters
Returns the current completion effect as an Option. This returns
Option.some(effect) when the Deferred is completed, Option.none()
otherwise.
When to use
Use to inspect whether a Deferred is already completed and retrieve its
stored completion effect when available.
Signature
declare function poll<A, E>(self: Deferred<A, E>): Effect<Option<Effect<A, E, never>>>Example
(Polling Deferred completion)
import { Deferred, Effect, Option } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number>() const beforeCompletion = yield* Deferred.poll(deferred) yield* Deferred.succeed(deferred, 42) const afterCompletion = yield* Deferred.poll(deferred) const afterValue = yield* Effect.transposeOption(afterCompletion) return [beforeCompletion, afterValue]})
await Effect.runPromise(program) // => [Option.none(), Option.some(42)]Guards
isDeferred
Checks whether a value is a Deferred.
When to use
Use to validate unknown values at runtime boundaries before treating them as
Deferred values.
Signature
declare function isDeferred<A, E>(u: unknown): u is Deferred<A, E>Models
A Deferred represents an asynchronous variable that can be set exactly
once, with the ability for an arbitrary number of fibers to suspend (by
calling Deferred.await) and automatically resume when the variable is set.
When to use
Use to coordinate multiple fibers around a value or failure that will be supplied exactly once.
Signature
interface Deferred<in out A, in out E = never> extends Variance<A, E>, Pipeable { effect?: Effect<A, E, never>; resumes?: Array<(effect: Effect<A, E>) => void>;}Example
(Creating a Deferred for inter-fiber communication)
import { Deferred, Effect, Fiber } from "effect"
const program = Effect.gen(function*() { const deferred: Deferred.Deferred<string> = yield* Deferred.make<string>() const producer = yield* Effect.forkChild( Effect.gen(function*() { yield* Deferred.succeed(deferred, "Hello, World!") }) )
const consumer = yield* Effect.forkChild(Deferred.await(deferred)) yield* Fiber.join(producer) return yield* Fiber.join(consumer)})
await Effect.runPromise(program) // => "Hello, World!"Other
Predicates
Returns true if this Deferred has already been completed with a value or
an error, false otherwise.
When to use
Use to check completion status inside an Effect workflow.
Signature
declare function isDone<A, E>(self: Deferred<A, E>): Effect<boolean>Example
(Checking Deferred completion)
import { Deferred, Effect } from "effect"
const program = Effect.gen(function*() { const deferred = yield* Deferred.make<number>() const beforeCompletion = yield* Deferred.isDone(deferred) yield* Deferred.succeed(deferred, 42) const afterCompletion = yield* Deferred.isDone(deferred) return [beforeCompletion, afterCompletion]})
await Effect.runPromise(program) // => [false, true]isDoneUnsafe
Returns whether this Deferred has already been completed synchronously.
When to use
Use to check Deferred completion synchronously in code that cannot return
an Effect, such as low-level integration code.
See
Signature
declare function isDoneUnsafe<A, E>(self: Deferred<A, E>): booleanUnsafe
doneUnsafe
Attempts to complete the Deferred synchronously with the specified
completion effect.
When to use
Use to complete a Deferred synchronously in low-level code that already has
the completion effect.
Details
This mutates the Deferred directly and should be reserved for low-level
code; prefer the effectful completion APIs when possible. Returns true if
this call completed the Deferred, or false if it was already completed.
Signature
declare function doneUnsafe<A, E>(self: Deferred<A, E>, effect: Effect<A, E>): booleanExample
(Completing a Deferred unsafely)
import { Deferred, Effect } from "effect"
const deferred = Deferred.makeUnsafe<number>()Deferred.doneUnsafe(deferred, Effect.succeed(42)) // => truemakeUnsafe
Creates an empty Deferred synchronously outside the Effect runtime.
When to use
Use to allocate a Deferred synchronously when direct allocation outside
Effect is required.
Signature
declare function makeUnsafe<A, E = never>(): Deferred<A, E>Example
(Creating a Deferred unsafely)
import { Deferred } from "effect"
const deferred = Deferred.makeUnsafe<number>()Deferred.isDoneUnsafe(deferred) // => false