Skip to content

Deferred.ts

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.

Since v2.0.0



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.

Example (Completing a Deferred from an effect result)

import { Deferred, Effect } from "effect"
// Define an effect that succeeds
const successEffect = Effect.succeed(42)
const program = Effect.gen(function* () {
// Create a deferred
const deferred = yield* Deferred.make<number, string>()
// Complete the deferred using the successEffect
const isCompleted = yield* Deferred.into(successEffect, deferred)
// Access the value of the deferred
const value = yield* Deferred.await(deferred)
console.log(value)
return isCompleted
})
Effect.runPromise(program).then(console.log)
// Output:
// 42
// true

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>
}

Source

Since v4.0.0

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.

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))
console.log(completed) // true
const value = yield* Deferred.await(deferred)
console.log(value) // 42
})

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>
}

Source

Since v2.0.0

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.

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))
console.log(completed) // true
const value = yield* Deferred.await(deferred)
console.log(value) // 42
})

See

  • complete for running an effect once and sharing its result
  • done for completing from an already computed Exit

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>
}

Source

Since v2.0.0

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.

Example (Killing a Deferred with a defect)

import { Deferred, Effect } from "effect"
const program = Effect.gen(function* () {
const deferred = yield* Deferred.make<number>()
const success = yield* Deferred.die(deferred, new Error("Something went wrong"))
console.log(success) // true
})

Signature

declare const die: {
(defect: unknown): <A, E>(self: Deferred<A, E>) => Effect<boolean>
<A, E>(self: Deferred<A, E>, defect: unknown): Effect<boolean>
}

Source

Since v2.0.0

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.

Example (Killing a Deferred with a lazy defect)

import { Deferred, Effect } from "effect"
const program = Effect.gen(function* () {
const deferred = yield* Deferred.make<number>()
const success = yield* Deferred.dieSync(deferred, () => new Error("Lazy error"))
console.log(success) // true
})

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>
}

Source

Since v2.0.0

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.

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))
const value = yield* Deferred.await(deferred)
console.log(value) // 42
})

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.Exit<A, E>): (self: Deferred<A, E>) => Effect<boolean>
<A, E>(self: Deferred<A, E>, exit: Exit.Exit<A, E>): Effect<boolean>
}

Source

Since v2.0.0

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.

Example (Failing a Deferred with an error)

import { Deferred, Effect } from "effect"
const program = Effect.gen(function* () {
const deferred = yield* Deferred.make<number, string>()
const success = yield* Deferred.fail(deferred, "Operation failed")
console.log(success) // true
})

Signature

declare const fail: {
<E>(error: E): <A>(self: Deferred<A, E>) => Effect<boolean>
<A, E>(self: Deferred<A, E>, error: E): Effect<boolean>
}

Source

Since v2.0.0

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.

Example (Failing a Deferred with a Cause)

import { Cause, Deferred, Effect } from "effect"
const program = Effect.gen(function* () {
const deferred = yield* Deferred.make<number, string>()
const success = yield* Deferred.failCause(deferred, Cause.fail("Operation failed"))
console.log(success) // true
})

Signature

declare const failCause: {
<E>(cause: Cause.Cause<E>): <A>(self: Deferred<A, E>) => Effect<boolean>
<A, E>(self: Deferred<A, E>, cause: Cause.Cause<E>): Effect<boolean>
}

Source

Since v2.0.0

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.

Example (Failing a Deferred with a lazy Cause)

import { Cause, Deferred, Effect } from "effect"
const program = Effect.gen(function* () {
const deferred = yield* Deferred.make<number, string>()
const success = yield* Deferred.failCauseSync(deferred, () => Cause.fail("Lazy error"))
console.log(success) // true
})

Signature

declare const failCauseSync: {
<E>(evaluate: LazyArg<Cause.Cause<E>>): <A>(self: Deferred<A, E>) => Effect<boolean>
<A, E>(self: Deferred<A, E>, evaluate: LazyArg<Cause.Cause<E>>): Effect<boolean>
}

Source

Since v2.0.0

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.

Example (Failing a Deferred with a lazy error)

import { Deferred, Effect } from "effect"
const program = Effect.gen(function* () {
const deferred = yield* Deferred.make<number, string>()
const success = yield* Deferred.failSync(deferred, () => "Lazy error")
console.log(success) // true
})

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>
}

Source

Since v2.0.0

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.

Example (Interrupting a Deferred)

import { Deferred, Effect } from "effect"
const program = Effect.gen(function* () {
const deferred = yield* Deferred.make<number>()
const success = yield* Deferred.interrupt(deferred)
console.log(success) // true
})

Signature

declare const interrupt: <A, E>(self: Deferred<A, E>) => Effect<boolean>

Source

Since v2.0.0

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.

Example (Interrupting a Deferred with a fiber id)

import { Deferred, Effect } from "effect"
const program = Effect.gen(function* () {
const deferred = yield* Deferred.make<number>()
const success = yield* Deferred.interruptWith(deferred, 42)
console.log(success) // true
})

Signature

declare const interruptWith: {
(fiberId: number): <A, E>(self: Deferred<A, E>) => Effect<boolean>
<A, E>(self: Deferred<A, E>, fiberId: number): Effect<boolean>
}

Source

Since v2.0.0

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.

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)
const value = yield* Deferred.await(deferred)
console.log(value) // 42
})

Signature

declare const succeed: {
<A>(value: A): <E>(self: Deferred<A, E>) => Effect<boolean>
<A, E>(self: Deferred<A, E>, value: A): Effect<boolean>
}

Source

Since v2.0.0

Computes 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.

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)
const value = yield* Deferred.await(deferred)
console.log(value) // 42
})

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>
}

Source

Since v2.0.0

Creates a new Deferred.

When to use

Use to allocate an empty Deferred inside an Effect workflow.

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)
const value = yield* Deferred.await(deferred)
console.log(value) // 42
})

Signature

declare const make: <A, E = never>() => Effect<Deferred<A, E>>

Source

Since v2.0.0

Retrieves the value of the Deferred, suspending the fiber running the workflow until the result is available.

When to use

Use to wait for a Deferred to be completed and resume with its success, failure, defect, or interruption.

Details

Awaiters observe the completion effect stored in the Deferred.

Example (Awaiting a Deferred value)

import { Deferred, Effect } from "effect"
const program = Effect.gen(function* () {
const deferred = yield* Deferred.make<number>()
yield* Deferred.succeed(deferred, 42)
const value = yield* Deferred.await(deferred)
console.log(value) // 42
})

See

  • complete for completing from an effect and memoizing its result
  • completeWith for completing with an effect directly

Signature

declare const await: <A, E>(self: Deferred<A, E>) => Effect<A, E>

Source

Since v2.0.0

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.

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)
console.log(beforeCompletion) // false
yield* Deferred.succeed(deferred, 42)
const afterCompletion = yield* Deferred.isDone(deferred)
console.log(afterCompletion) // true
})

Signature

declare const isDone: <A, E>(self: Deferred<A, E>) => Effect<boolean>

Source

Since v2.0.0

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

  • isDone for checking completion inside Effect
  • poll for reading the completed effect when available

Signature

declare const isDoneUnsafe: <A, E>(self: Deferred<A, E>) => boolean

Source

Since v4.0.0

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.

Example (Polling Deferred completion)

import { Deferred, Effect } from "effect"
const program = Effect.gen(function* () {
const deferred = yield* Deferred.make<number>()
const beforeCompletion = yield* Deferred.poll(deferred)
console.log(beforeCompletion._tag === "None") // true
yield* Deferred.succeed(deferred, 42)
const afterCompletion = yield* Deferred.poll(deferred)
console.log(afterCompletion._tag === "Some") // true
})

Signature

declare const poll: <A, E>(self: Deferred<A, E>) => Effect<Option.Option<Effect<A, E>>>

Source

Since v2.0.0

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 const isDeferred: <A, E>(u: unknown) => u is Deferred<A, E>

Source

Since v4.0.0

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.

Example (Creating a Deferred for inter-fiber communication)

import { Deferred, Effect, Fiber } from "effect"
// Create and use a Deferred for inter-fiber communication
const program = Effect.gen(function* () {
// Create a Deferred that will hold a string value
const deferred: Deferred.Deferred<string> = yield* Deferred.make<string>()
// Fork a fiber that will set the deferred value
const producer = yield* Effect.forkChild(
Effect.gen(function* () {
yield* Effect.sleep("100 millis")
yield* Deferred.succeed(deferred, "Hello, World!")
})
)
// Fork a fiber that will await the deferred value
const consumer = yield* Effect.forkChild(
Effect.gen(function* () {
const value = yield* Deferred.await(deferred)
console.log("Received:", value)
return value
})
)
// Wait for both fibers to complete
yield* Fiber.join(producer)
const result = yield* Fiber.join(consumer)
return result
})

Signature

export interface Deferred<in out A, in out E = never> extends Deferred.Variance<A, E>, Pipeable {
effect?: Effect<A, E>
resumes?: Array<(effect: Effect<A, E>) => void> | undefined
}

Source

Since v2.0.0

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.

Example (Completing a Deferred unsafely)

import { Deferred, Effect } from "effect"
const deferred = Deferred.makeUnsafe<number>()
const success = Deferred.doneUnsafe(deferred, Effect.succeed(42))
console.log(success) // true

Signature

declare const doneUnsafe: <A, E>(self: Deferred<A, E>, effect: Effect<A, E>) => boolean

Source

Since v4.0.0

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.

Example (Creating a Deferred unsafely)

import { Deferred } from "effect"
const deferred = Deferred.makeUnsafe<number>()
console.log(deferred)

Signature

declare const makeUnsafe: <A, E = never>() => Deferred<A, E>

Source

Since v4.0.0

Companion namespace containing type-level metadata for Deferred.

When to use

Use to reference type-level metadata associated with Deferred.

Source

Since v2.0.0

Type-level variance marker for the value and error channels of Deferred.

When to use

Use to carry the value and error type parameters for Deferred in Effect’s type machinery.

Details

This interface is part of the public type structure and is not intended to be constructed directly.

Signature

export interface Variance<in out A, in out E> {
readonly [TypeId]: {
readonly _A: Types.Invariant<A>
readonly _E: Types.Invariant<E>
}
}

Source

Since v2.0.0