Skip to content

队列

一个 Queue 是一个轻量级的内存队列,具有内置的背压机制,支持异步、纯函数式和类型安全的数据处理。

一个 Queue<A> 存储类型为 A 的值,并提供两个基本操作:

API描述
Queue.offer向队列添加一个类型为 A 的值。
Queue.take移除并返回队列中最旧的值。

示例(添加和检索项目)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Queue
Queue
} from "effect"
const
const program: Effect.Effect<number, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>>, number>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>>, number, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
// 创建一个容量为 100 的有界队列
const
const queue: Queue.Queue<number>
queue
= yield*
import Queue
Queue
.
const bounded: <number>(requestedCapacity: number) => Effect.Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue. When the capacity of the queue is reached, any additional calls to offer will be suspended until there is more room in the queue.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

bounded
<number>(100)
// 向队列添加 1
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 1)
// 检索并移除最旧的值
const
const value: number
value
= yield*
import Queue
Queue
.
const take: <number>(self: Queue.Dequeue<number>) => Effect.Effect<number, never, never>

Takes the oldest value in the queue. If the queue is empty, this will return a computation that resumes when an item has been added to the queue.

@since2.0.0

take
(
const queue: Queue.Queue<number>
queue
)
return
const value: number
value
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <number, never>(effect: Effect.Effect<number, never, never>, options?: {
readonly signal?: AbortSignal | undefined;
} | undefined) => Promise<number>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

Example (Handling a Failing Effect as a Rejected Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.fail("my error")).catch(console.error)
// Output:
// (FiberFailure) Error: my error

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@since2.0.0

runPromise
(
const program: Effect.Effect<number, never, never>
program
).
Promise<number>.then<void, never>(onfulfilled?: ((value: number) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<void>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
)
// 输出: 1

队列可以是有界的(具有指定容量)或无界的(没有限制)。不同类型的队列在达到容量时以不同方式处理新值。

有界队列在满时应用背压,这意味着任何 Queue.offer 操作都会暂停,直到有空间为止。

示例(创建有界队列)

import {
import Queue
Queue
} from "effect"
// 创建一个容量为 100 的有界队列
const
const boundedQueue: Effect<Queue.Queue<number>, never, never>
boundedQueue
=
import Queue
Queue
.
const bounded: <number>(requestedCapacity: number) => Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue. When the capacity of the queue is reached, any additional calls to offer will be suspended until there is more room in the queue.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

bounded
<number>(100)

丢弃队列在队列满时丢弃新值。

示例(创建丢弃队列)

import {
import Queue
Queue
} from "effect"
// 创建一个容量为 100 的丢弃队列
const
const droppingQueue: Effect<Queue.Queue<number>, never, never>
droppingQueue
=
import Queue
Queue
.
const dropping: <number>(requestedCapacity: number) => Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue with the dropping strategy.

When the capacity of the queue is reached, new elements will be dropped and the old elements will remain.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

dropping
<number>(100)

滑动队列在达到容量时移除旧值以为新值腾出空间。

示例(创建滑动队列)

import {
import Queue
Queue
} from "effect"
// 创建一个容量为 100 的滑动队列
const
const slidingQueue: Effect<Queue.Queue<number>, never, never>
slidingQueue
=
import Queue
Queue
.
const sliding: <number>(requestedCapacity: number) => Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue with the sliding strategy.

When the capacity of the queue is reached, new elements will be added and the old elements will be dropped.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

sliding
<number>(100)

无界队列没有容量限制,允许无限制地添加。

示例(创建无界队列)

import {
import Queue
Queue
} from "effect"
// 创建一个没有容量限制的无界队列
const
const unboundedQueue: Effect<Queue.Queue<number>, never, never>
unboundedQueue
=
import Queue
Queue
.
const unbounded: <number>() => Effect<Queue.Queue<number>, never, never>

Creates a new unbounded Queue.

@since2.0.0

unbounded
<number>()

使用 Queue.offer 向队列添加值。

示例(添加单个项目)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Queue
Queue
} from "effect"
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>>, void, never>) => Effect.Effect<void, never, never> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const queue: Queue.Queue<number>
queue
= yield*
import Queue
Queue
.
const bounded: <number>(requestedCapacity: number) => Effect.Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue. When the capacity of the queue is reached, any additional calls to offer will be suspended until there is more room in the queue.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

bounded
<number>(100)
// 向队列添加 1
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 1)
})

当使用背压队列时,如果队列满了,Queue.offer 会暂停。为了避免阻塞主纤程,您可以分叉 Queue.offer 操作。

示例(使用 Effect.fork 处理满队列)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Queue
Queue
,
import Fiber
Fiber
} from "effect"
const
const program: Effect.Effect<number, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>> | YieldWrap<Effect.Effect<Fiber.RuntimeFiber<boolean, never>, never, never>>, number>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<...> | YieldWrap<...>, number, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const queue: Queue.Queue<number>
queue
= yield*
import Queue
Queue
.
const bounded: <number>(requestedCapacity: number) => Effect.Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue. When the capacity of the queue is reached, any additional calls to offer will be suspended until there is more room in the queue.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

bounded
<number>(1)
// 用一个项目填充队列
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 1)
// 尝试添加第二个项目会暂停,因为队列已满
const
const fiber: Fiber.RuntimeFiber<boolean, never>
fiber
= yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <boolean, never, never>(self: Effect.Effect<boolean, never, never>) => Effect.Effect<Fiber.RuntimeFiber<boolean, never>, never, never>

Creates a new fiber to run an effect concurrently.

Details

This function takes an effect and forks it into a separate fiber, allowing it to run concurrently without blocking the original effect. The new fiber starts execution immediately after being created, and the fiber object is returned immediately without waiting for the effect to begin. This is useful when you want to run tasks concurrently while continuing other tasks in the parent fiber.

The forked fiber is attached to the parent fiber's scope. This means that when the parent fiber terminates, the child fiber will also be terminated automatically. This feature, known as "auto supervision," ensures that no fibers are left running unintentionally. If you prefer not to have this auto supervision behavior, you can use

forkDaemon

or

forkIn

.

When to Use

Use this function when you need to run an effect concurrently without blocking the current execution flow. For example, you might use it to launch background tasks or concurrent computations. However, working with fibers can be complex, so before using this function directly, you might want to explore higher-level functions like

raceWith

,

zip

, or others that can manage concurrency for you.

Example

import { Effect } from "effect"
const fib = (n: number): Effect.Effect<number> =>
n < 2
? Effect.succeed(n)
: Effect.zipWith(fib(n - 1), fib(n - 2), (a, b) => a + b)
// ┌─── Effect<RuntimeFiber<number, never>, never, never>
// ▼
const fib10Fiber = Effect.fork(fib(10))

@seeforkWithErrorHandler for a version that allows you to handle errors.

@since2.0.0

fork
(
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 2))
// 清空队列以腾出空间
yield*
import Queue
Queue
.
const take: <number>(self: Queue.Dequeue<number>) => Effect.Effect<number, never, never>

Takes the oldest value in the queue. If the queue is empty, this will return a computation that resumes when an item has been added to the queue.

@since2.0.0

take
(
const queue: Queue.Queue<number>
queue
)
// 加入纤程,完成暂停的 offer
yield*
import Fiber
Fiber
.
const join: <boolean, never>(self: Fiber.Fiber<boolean, never>) => Effect.Effect<boolean, never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<boolean, never>
fiber
)
// 返回添加后队列的大小
return yield*
import Queue
Queue
.
const size: <number>(self: Queue.Enqueue<number> | Queue.Dequeue<number>) => Effect.Effect<number>

Retrieves the size of the queue, which is equal to the number of elements in the queue. This may be negative if fibers are suspended waiting for elements to be added to the queue.

@since2.0.0

size
(
const queue: Queue.Queue<number>
queue
)
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <number, never>(effect: Effect.Effect<number, never, never>, options?: {
readonly signal?: AbortSignal | undefined;
} | undefined) => Promise<number>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

Example (Handling a Failing Effect as a Rejected Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.fail("my error")).catch(console.error)
// Output:
// (FiberFailure) Error: my error

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@since2.0.0

runPromise
(
const program: Effect.Effect<number, never, never>
program
).
Promise<number>.then<void, never>(onfulfilled?: ((value: number) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<void>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
)
// 输出: 1

您也可以使用 Queue.offerAll 一次添加多个项目。

示例(添加多个项目)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Queue
Queue
,
import Array
Array
} from "effect"
const
const program: Effect.Effect<number, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>>, number>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<number, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>>, number, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const queue: Queue.Queue<number>
queue
= yield*
import Queue
Queue
.
const bounded: <number>(requestedCapacity: number) => Effect.Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue. When the capacity of the queue is reached, any additional calls to offer will be suspended until there is more room in the queue.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

bounded
<number>(100)
const
const items: [number, ...number[]]
items
=
import Array
Array
.
const range: (start: number, end: number) => Array.NonEmptyArray<number>

Return a NonEmptyArray containing a range of integers, including both endpoints.

Example

import { range } from "effect/Array"
const result = range(1, 3)
console.log(result) // [1, 2, 3]

@since2.0.0

range
(1, 10)
// 一次将所有项目添加到队列
yield*
import Queue
Queue
.
const offerAll: <number>(self: Queue.Enqueue<number>, iterable: Iterable<number>) => Effect.Effect<boolean> (+1 overload)

For Bounded Queue: uses the BackPressure Strategy, places the values in the queue and always returns true. If the queue has reached capacity, then the fiber performing the offerAll will be suspended until there is room in the queue.

For Unbounded Queue: Places all values in the queue and returns true.

For Sliding Queue: uses Sliding Strategy If there is room in the queue, it places the values otherwise it removes the old elements and enqueues the new ones. Always returns true.

For Dropping Queue: uses Dropping Strategy, It places the values in the queue but if there is no room it will not enqueue them and return false.

@since2.0.0

offerAll
(
const queue: Queue.Queue<number>
queue
,
const items: [number, ...number[]]
items
)
// 返回添加后队列的大小
return yield*
import Queue
Queue
.
const size: <number>(self: Queue.Enqueue<number> | Queue.Dequeue<number>) => Effect.Effect<number>

Retrieves the size of the queue, which is equal to the number of elements in the queue. This may be negative if fibers are suspended waiting for elements to be added to the queue.

@since2.0.0

size
(
const queue: Queue.Queue<number>
queue
)
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <number, never>(effect: Effect.Effect<number, never, never>, options?: {
readonly signal?: AbortSignal | undefined;
} | undefined) => Promise<number>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

Example (Handling a Failing Effect as a Rejected Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.fail("my error")).catch(console.error)
// Output:
// (FiberFailure) Error: my error

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@since2.0.0

runPromise
(
const program: Effect.Effect<number, never, never>
program
).
Promise<number>.then<void, never>(onfulfilled?: ((value: number) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<void>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
)
// 输出: 10

Queue.take 操作移除并返回队列中最旧的项目。如果队列为空,Queue.take 将暂停,只有在添加项目时才会恢复。为了防止阻塞,您可以将 Queue.take 操作分叉到新纤程中。

示例(在纤程中等待项目)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Queue
Queue
,
import Fiber
Fiber
} from "effect"
const
const program: Effect.Effect<string, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<Queue.Queue<string>, never, never>> | YieldWrap<Effect.Effect<Fiber.RuntimeFiber<string, never>, never, never>> | YieldWrap<Effect.Effect<string, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>>, string>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<Queue.Queue<string>, never, never>> | YieldWrap<Effect.Effect<Fiber.RuntimeFiber<string, never>, never, never>> | YieldWrap<...> | YieldWrap<...>, string, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const queue: Queue.Queue<string>
queue
= yield*
import Queue
Queue
.
const bounded: <string>(requestedCapacity: number) => Effect.Effect<Queue.Queue<string>, never, never>

Makes a new bounded Queue. When the capacity of the queue is reached, any additional calls to offer will be suspended until there is more room in the queue.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

bounded
<string>(100)
// 此 take 操作将暂停,因为队列为空
const
const fiber: Fiber.RuntimeFiber<string, never>
fiber
= yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <string, never, never>(self: Effect.Effect<string, never, never>) => Effect.Effect<Fiber.RuntimeFiber<string, never>, never, never>

Creates a new fiber to run an effect concurrently.

Details

This function takes an effect and forks it into a separate fiber, allowing it to run concurrently without blocking the original effect. The new fiber starts execution immediately after being created, and the fiber object is returned immediately without waiting for the effect to begin. This is useful when you want to run tasks concurrently while continuing other tasks in the parent fiber.

The forked fiber is attached to the parent fiber's scope. This means that when the parent fiber terminates, the child fiber will also be terminated automatically. This feature, known as "auto supervision," ensures that no fibers are left running unintentionally. If you prefer not to have this auto supervision behavior, you can use

forkDaemon

or

forkIn

.

When to Use

Use this function when you need to run an effect concurrently without blocking the current execution flow. For example, you might use it to launch background tasks or concurrent computations. However, working with fibers can be complex, so before using this function directly, you might want to explore higher-level functions like

raceWith

,

zip

, or others that can manage concurrency for you.

Example

import { Effect } from "effect"
const fib = (n: number): Effect.Effect<number> =>
n < 2
? Effect.succeed(n)
: Effect.zipWith(fib(n - 1), fib(n - 2), (a, b) => a + b)
// ┌─── Effect<RuntimeFiber<number, never>, never, never>
// ▼
const fib10Fiber = Effect.fork(fib(10))

@seeforkWithErrorHandler for a version that allows you to handle errors.

@since2.0.0

fork
(
import Queue
Queue
.
const take: <string>(self: Queue.Dequeue<string>) => Effect.Effect<string, never, never>

Takes the oldest value in the queue. If the queue is empty, this will return a computation that resumes when an item has been added to the queue.

@since2.0.0

take
(
const queue: Queue.Queue<string>
queue
))
// 向队列添加一个项目
yield*
import Queue
Queue
.
const offer: <string>(self: Queue.Enqueue<string>, value: string) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<string>
queue
, "something")
// 加入纤程以获取 take 操作的结果
const
const value: string
value
= yield*
import Fiber
Fiber
.
const join: <string, never>(self: Fiber.Fiber<string, never>) => Effect.Effect<string, never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<string, never>
fiber
)
return
const value: string
value
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <string, never>(effect: Effect.Effect<string, never, never>, options?: {
readonly signal?: AbortSignal | undefined;
} | undefined) => Promise<string>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

Example (Handling a Failing Effect as a Rejected Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.fail("my error")).catch(console.error)
// Output:
// (FiberFailure) Error: my error

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@since2.0.0

runPromise
(
const program: Effect.Effect<string, never, never>
program
).
Promise<string>.then<void, never>(onfulfilled?: ((value: string) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<void>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
)
// 输出: something

要在不暂停的情况下检索队列的第一个项目,请使用 Queue.poll。如果队列为空,Queue.poll 返回 None;如果有项目,它将其包装在 Some 中。

示例(轮询项目)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Queue
Queue
} from "effect"
const
const program: Effect.Effect<Option<number>, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<Option<number>, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>>, Option<number>>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<Option<number>, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>>, Option<...>, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const queue: Queue.Queue<number>
queue
= yield*
import Queue
Queue
.
const bounded: <number>(requestedCapacity: number) => Effect.Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue. When the capacity of the queue is reached, any additional calls to offer will be suspended until there is more room in the queue.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

bounded
<number>(100)
// 向队列添加项目
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 10)
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 20)
// 如果可用,检索第一个项目
const
const head: Option<number>
head
= yield*
import Queue
Queue
.
const poll: <number>(self: Queue.Dequeue<number>) => Effect.Effect<Option<number>, never, never>

Returns the first value in the Queue as a Some<A>, or None if the queue is empty.

@since2.0.0

poll
(
const queue: Queue.Queue<number>
queue
)
return
const head: Option<number>
head
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <Option<number>, never>(effect: Effect.Effect<Option<number>, never, never>, options?: {
readonly signal?: AbortSignal | undefined;
} | undefined) => Promise<Option<number>>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

Example (Handling a Failing Effect as a Rejected Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.fail("my error")).catch(console.error)
// Output:
// (FiberFailure) Error: my error

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@since2.0.0

runPromise
(
const program: Effect.Effect<Option<number>, never, never>
program
).
Promise<Option<number>>.then<void, never>(onfulfilled?: ((value: Option<number>) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<void>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
)
/*
输出:
{
_id: "Option",
_tag: "Some",
value: 10
}
*/

要检索多个项目,请使用 Queue.takeUpTo,它返回最多指定数量的项目。 如果没有足够的项目,它会返回所有可用项目而不等待更多。

当不需要确切数量的项目时,此函数对批处理特别有用。它确保程序继续处理当前可用的任何数据。

如果您需要在继续之前等待确切数量的项目,请考虑使用 takeN

示例(取最多 N 个项目)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Queue
Queue
} from "effect"
const
const program: Effect.Effect<string, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>> | YieldWrap<Effect.Effect<Chunk<number>, never, never>>, string>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>> | YieldWrap<Effect.Effect<Chunk<number>, never, never>>, string, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const queue: Queue.Queue<number>
queue
= yield*
import Queue
Queue
.
const bounded: <number>(requestedCapacity: number) => Effect.Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue. When the capacity of the queue is reached, any additional calls to offer will be suspended until there is more room in the queue.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

bounded
<number>(100)
// 向队列添加项目
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 1)
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 2)
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 3)
// 检索最多 2 个项目
const
const chunk: Chunk<number>
chunk
= yield*
import Queue
Queue
.
const takeUpTo: <number>(self: Queue.Dequeue<number>, max: number) => Effect.Effect<Chunk<number>, never, never> (+1 overload)

Takes up to max number of values from the queue.

@since2.0.0

takeUpTo
(
const queue: Queue.Queue<number>
queue
, 2)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
const chunk: Chunk<number>
chunk
)
return "some result"
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <string, never>(effect: Effect.Effect<string, never, never>, options?: {
readonly signal?: AbortSignal | undefined;
} | undefined) => Promise<string>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

Example (Handling a Failing Effect as a Rejected Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.fail("my error")).catch(console.error)
// Output:
// (FiberFailure) Error: my error

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@since2.0.0

runPromise
(
const program: Effect.Effect<string, never, never>
program
).
Promise<string>.then<void, never>(onfulfilled?: ((value: string) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<void>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
)
/*
输出:
{ _id: 'Chunk', values: [ 1, 2 ] }
some result
*/

从队列中取指定数量的元素。如果队列没有足够的元素,操作会暂停,直到所需数量的元素可用。

此函数对于需要一次处理确切数量项目的场景很有用,确保操作在批次完成之前不会继续。

示例(取固定数量的项目)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Queue
Queue
,
import Fiber
Fiber
} from "effect"
const
const program: Effect.Effect<string, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, string>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, string, never>) => Effect.Effect<string, never, never> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
// 创建一个可容纳最多 100 个元素的队列
const
const queue: Queue.Queue<number>
queue
= yield*
import Queue
Queue
.
const bounded: <number>(requestedCapacity: number) => Effect.Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue. When the capacity of the queue is reached, any additional calls to offer will be suspended until there is more room in the queue.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

bounded
<number>(100)
// 分叉一个尝试从队列取 3 个项目的纤程
const
const fiber: Fiber.RuntimeFiber<void, never>
fiber
= yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <void, never, never>(self: Effect.Effect<void, never, never>) => Effect.Effect<Fiber.RuntimeFiber<void, never>, never, never>

Creates a new fiber to run an effect concurrently.

Details

This function takes an effect and forks it into a separate fiber, allowing it to run concurrently without blocking the original effect. The new fiber starts execution immediately after being created, and the fiber object is returned immediately without waiting for the effect to begin. This is useful when you want to run tasks concurrently while continuing other tasks in the parent fiber.

The forked fiber is attached to the parent fiber's scope. This means that when the parent fiber terminates, the child fiber will also be terminated automatically. This feature, known as "auto supervision," ensures that no fibers are left running unintentionally. If you prefer not to have this auto supervision behavior, you can use

forkDaemon

or

forkIn

.

When to Use

Use this function when you need to run an effect concurrently without blocking the current execution flow. For example, you might use it to launch background tasks or concurrent computations. However, working with fibers can be complex, so before using this function directly, you might want to explore higher-level functions like

raceWith

,

zip

, or others that can manage concurrency for you.

Example

import { Effect } from "effect"
const fib = (n: number): Effect.Effect<number> =>
n < 2
? Effect.succeed(n)
: Effect.zipWith(fib(n - 1), fib(n - 2), (a, b) => a + b)
// ┌─── Effect<RuntimeFiber<number, never>, never, never>
// ▼
const fib10Fiber = Effect.fork(fib(10))

@seeforkWithErrorHandler for a version that allows you to handle errors.

@since2.0.0

fork
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<Chunk<number>, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<Chunk<number>, never, never>>, void, never>) => Effect.Effect<void, never, never> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
("尝试从队列取 3 个项目...")
const
const chunk: Chunk<number>
chunk
= yield*
import Queue
Queue
.
const takeN: <number>(self: Queue.Dequeue<number>, n: number) => Effect.Effect<Chunk<number>, never, never> (+1 overload)

Takes the specified number of elements from the queue. If there are fewer than the specified number of elements available, it suspends until they become available.

@since2.0.0

takeN
(
const queue: Queue.Queue<number>
queue
, 3)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(`成功取了 3 个项目: ${
const chunk: Chunk<number>
chunk
}`)
})
)
// 最初只提供 2 个项目
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 1)
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 2)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
"提供了 2 个项目。纤程现在正在等待第 3 个项目..."
)
// 模拟一些延迟
yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const sleep: (duration: DurationInput) => Effect.Effect<void>

Suspends the execution of an effect for a specified Duration.

Details

This function pauses the execution of an effect for a given duration. It is asynchronous, meaning that it does not block the fiber executing the effect. Instead, the fiber is suspended during the delay period and can resume once the specified time has passed.

The duration can be specified using various formats supported by the Duration module, such as a string ("2 seconds") or numeric value representing milliseconds.

Example

import { Effect } from "effect"
const program = Effect.gen(function*() {
console.log("Starting task...")
yield* Effect.sleep("3 seconds") // Waits for 3 seconds
console.log("Task completed!")
})
Effect.runFork(program)
// Output:
// Starting task...
// Task completed!

@since2.0.0

sleep
("2 seconds")
// 提供第 3 个项目,这将解除 takeN 调用的阻塞
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 3)
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
("提供了第 3 个项目,这应该解除纤程的阻塞。")
// 等待纤程完成
yield*
import Fiber
Fiber
.
const join: <void, never>(self: Fiber.Fiber<void, never>) => Effect.Effect<void, never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<void, never>
fiber
)
return "some result"
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <string, never>(effect: Effect.Effect<string, never, never>, options?: {
readonly signal?: AbortSignal | undefined;
} | undefined) => Promise<string>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

Example (Handling a Failing Effect as a Rejected Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.fail("my error")).catch(console.error)
// Output:
// (FiberFailure) Error: my error

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@since2.0.0

runPromise
(
const program: Effect.Effect<string, never, never>
program
).
Promise<string>.then<void, never>(onfulfilled?: ((value: string) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<void>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
)
/*
输出:
提供了 2 个项目。纤程现在正在等待第 3 个项目...
尝试从队列取 3 个项目...
提供了第 3 个项目,这应该解除纤程的阻塞。
成功取了 3 个项目: {
"_id": "Chunk",
"values": [
1,
2,
3
]
}
some result
*/

要一次从队列中检索所有项目,请使用 Queue.takeAll。此操作立即完成,如果队列为空则返回空集合。

示例(取所有项目)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Queue
Queue
} from "effect"
const
const program: Effect.Effect<Chunk<number>, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<Chunk<number>, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>>, Chunk<number>>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<Chunk<number>, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>>, Chunk<...>, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const queue: Queue.Queue<number>
queue
= yield*
import Queue
Queue
.
const bounded: <number>(requestedCapacity: number) => Effect.Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue. When the capacity of the queue is reached, any additional calls to offer will be suspended until there is more room in the queue.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

bounded
<number>(100)
// 向队列添加项目
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 10)
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 20)
yield*
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
const queue: Queue.Queue<number>
queue
, 30)
// 从队列检索所有项目
const
const chunk: Chunk<number>
chunk
= yield*
import Queue
Queue
.
const takeAll: <number>(self: Queue.Dequeue<number>) => Effect.Effect<Chunk<number>, never, never>

Takes all the values in the queue and returns the values. If the queue is empty returns an empty collection.

@since2.0.0

takeAll
(
const queue: Queue.Queue<number>
queue
)
return
const chunk: Chunk<number>
chunk
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <Chunk<number>, never>(effect: Effect.Effect<Chunk<number>, never, never>, options?: {
readonly signal?: AbortSignal | undefined;
} | undefined) => Promise<Chunk<number>>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

Example (Handling a Failing Effect as a Rejected Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.fail("my error")).catch(console.error)
// Output:
// (FiberFailure) Error: my error

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@since2.0.0

runPromise
(
const program: Effect.Effect<Chunk<number>, never, never>
program
).
Promise<Chunk<number>>.then<void, never>(onfulfilled?: ((value: Chunk<number>) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<void>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
)
/*
输出:
{
_id: "Chunk",
values: [ 10, 20, 30 ]
}
*/

Queue.shutdown 操作允许您中断当前在 offer*take* 操作上暂停的所有纤程。此操作还会清空队列,并使任何未来的 offer*take* 调用立即终止。

示例(在队列关闭时中断纤程)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Queue
Queue
,
import Fiber
Fiber
} from "effect"
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<void, never, never> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const queue: Queue.Queue<number>
queue
= yield*
import Queue
Queue
.
const bounded: <number>(requestedCapacity: number) => Effect.Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue. When the capacity of the queue is reached, any additional calls to offer will be suspended until there is more room in the queue.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

bounded
<number>(3)
// 分叉一个等待从队列取项目的纤程
const
const fiber: Fiber.RuntimeFiber<number, never>
fiber
= yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <number, never, never>(self: Effect.Effect<number, never, never>) => Effect.Effect<Fiber.RuntimeFiber<number, never>, never, never>

Creates a new fiber to run an effect concurrently.

Details

This function takes an effect and forks it into a separate fiber, allowing it to run concurrently without blocking the original effect. The new fiber starts execution immediately after being created, and the fiber object is returned immediately without waiting for the effect to begin. This is useful when you want to run tasks concurrently while continuing other tasks in the parent fiber.

The forked fiber is attached to the parent fiber's scope. This means that when the parent fiber terminates, the child fiber will also be terminated automatically. This feature, known as "auto supervision," ensures that no fibers are left running unintentionally. If you prefer not to have this auto supervision behavior, you can use

forkDaemon

or

forkIn

.

When to Use

Use this function when you need to run an effect concurrently without blocking the current execution flow. For example, you might use it to launch background tasks or concurrent computations. However, working with fibers can be complex, so before using this function directly, you might want to explore higher-level functions like

raceWith

,

zip

, or others that can manage concurrency for you.

Example

import { Effect } from "effect"
const fib = (n: number): Effect.Effect<number> =>
n < 2
? Effect.succeed(n)
: Effect.zipWith(fib(n - 1), fib(n - 2), (a, b) => a + b)
// ┌─── Effect<RuntimeFiber<number, never>, never, never>
// ▼
const fib10Fiber = Effect.fork(fib(10))

@seeforkWithErrorHandler for a version that allows you to handle errors.

@since2.0.0

fork
(
import Queue
Queue
.
const take: <number>(self: Queue.Dequeue<number>) => Effect.Effect<number, never, never>

Takes the oldest value in the queue. If the queue is empty, this will return a computation that resumes when an item has been added to the queue.

@since2.0.0

take
(
const queue: Queue.Queue<number>
queue
))
// 关闭队列,中断纤程
yield*
import Queue
Queue
.
const shutdown: <number>(self: Queue.Enqueue<number> | Queue.Dequeue<number>) => Effect.Effect<void>

Interrupts any fibers that are suspended on offer or take. Future calls to offer* and take* will be interrupted immediately.

@since2.0.0

shutdown
(
const queue: Queue.Queue<number>
queue
)
// 加入被中断的纤程
yield*
import Fiber
Fiber
.
const join: <number, never>(self: Fiber.Fiber<number, never>) => Effect.Effect<number, never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<number, never>
fiber
)
})

Queue.awaitShutdown 操作可用于在队列关闭时运行 effect。它等待直到队列关闭,如果队列已经关闭则立即恢复。

示例(等待队列关闭)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Queue
Queue
,
import Fiber
Fiber
,
import Console
Console
} from "effect"
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<void, never, never> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const queue: Queue.Queue<number>
queue
= yield*
import Queue
Queue
.
const bounded: <number>(requestedCapacity: number) => Effect.Effect<Queue.Queue<number>, never, never>

Makes a new bounded Queue. When the capacity of the queue is reached, any additional calls to offer will be suspended until there is more room in the queue.

Note: When possible use only power of 2 capacities; this will provide better performance by utilising an optimised version of the underlying RingBuffer.

@since2.0.0

bounded
<number>(3)
// 分叉一个纤程以等待队列关闭并记录消息
const
const fiber: Fiber.RuntimeFiber<void, never>
fiber
= yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <void, never, never>(self: Effect.Effect<void, never, never>) => Effect.Effect<Fiber.RuntimeFiber<void, never>, never, never>

Creates a new fiber to run an effect concurrently.

Details

This function takes an effect and forks it into a separate fiber, allowing it to run concurrently without blocking the original effect. The new fiber starts execution immediately after being created, and the fiber object is returned immediately without waiting for the effect to begin. This is useful when you want to run tasks concurrently while continuing other tasks in the parent fiber.

The forked fiber is attached to the parent fiber's scope. This means that when the parent fiber terminates, the child fiber will also be terminated automatically. This feature, known as "auto supervision," ensures that no fibers are left running unintentionally. If you prefer not to have this auto supervision behavior, you can use

forkDaemon

or

forkIn

.

When to Use

Use this function when you need to run an effect concurrently without blocking the current execution flow. For example, you might use it to launch background tasks or concurrent computations. However, working with fibers can be complex, so before using this function directly, you might want to explore higher-level functions like

raceWith

,

zip

, or others that can manage concurrency for you.

Example

import { Effect } from "effect"
const fib = (n: number): Effect.Effect<number> =>
n < 2
? Effect.succeed(n)
: Effect.zipWith(fib(n - 1), fib(n - 2), (a, b) => a + b)
// ┌─── Effect<RuntimeFiber<number, never>, never, never>
// ▼
const fib10Fiber = Effect.fork(fib(10))

@seeforkWithErrorHandler for a version that allows you to handle errors.

@since2.0.0

fork
(
import Queue
Queue
.
const awaitShutdown: <number>(self: Queue.Enqueue<number> | Queue.Dequeue<number>) => Effect.Effect<void>

Waits until the queue is shutdown. The Effect returned by this method will not resume until the queue has been shutdown. If the queue is already shutdown, the Effect will resume right away.

@since2.0.0

awaitShutdown
(
const queue: Queue.Queue<number>
queue
).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<void, never, never>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<void, never, never> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const andThen: <Effect.Effect<void, never, never>>(f: Effect.Effect<void, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, E, R> (+3 overloads)

Chains two actions, where the second action can depend on the result of the first.

Syntax

const transformedEffect = pipe(myEffect, Effect.andThen(anotherEffect))
// or
const transformedEffect = Effect.andThen(myEffect, anotherEffect)
// or
const transformedEffect = myEffect.pipe(Effect.andThen(anotherEffect))

When to Use

Use andThen when you need to run multiple actions in sequence, with the second action depending on the result of the first. This is useful for combining effects or handling computations that must happen in order.

Details

The second action can be:

  • A constant value (similar to

as

)

  • A function returning a value (similar to

map

)

  • A Promise
  • A function returning a Promise
  • An Effect
  • A function returning an Effect (similar to

flatMap

)

Note: andThen works well with both Option and Either types, treating them as effects.

Example (Applying a Discount Based on Fetched Amount)

import { pipe, Effect } from "effect"
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Using Effect.map and Effect.flatMap
const result1 = pipe(
fetchTransactionAmount,
Effect.map((amount) => amount * 2),
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result1).then(console.log)
// Output: 190
// Using Effect.andThen
const result2 = pipe(
fetchTransactionAmount,
Effect.andThen((amount) => amount * 2),
Effect.andThen((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result2).then(console.log)
// Output: 190

@since2.0.0

andThen
(
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
("正在关闭"))
)
)
// 关闭队列,触发纤程中的等待
yield*
import Queue
Queue
.
const shutdown: <number>(self: Queue.Enqueue<number> | Queue.Dequeue<number>) => Effect.Effect<void>

Interrupts any fibers that are suspended on offer or take. Future calls to offer* and take* will be interrupted immediately.

@since2.0.0

shutdown
(
const queue: Queue.Queue<number>
queue
)
yield*
import Fiber
Fiber
.
const join: <void, never>(self: Fiber.Fiber<void, never>) => Effect.Effect<void, never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<void, never>
fiber
)
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <void, never>(effect: Effect.Effect<void, never, never>, options?: {
readonly signal?: AbortSignal | undefined;
} | undefined) => Promise<void>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

Example (Handling a Failing Effect as a Rejected Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.fail("my error")).catch(console.error)
// Output:
// (FiberFailure) Error: my error

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
// 输出: 正在关闭

有时,您可能希望代码的某些部分只向队列添加值(Enqueue)或只从队列检索值(Dequeue)。Effect 提供接口来强制执行这些特定功能。

向队列添加值的所有方法都由 Enqueue 接口定义。这将队列限制为仅提供操作。

示例(将队列限制为仅提供操作)

import {
import Queue
Queue
} from "effect"
const
const send: (offerOnlyQueue: Queue.Enqueue<number>, value: number) => Effect<boolean, never, never>
send
= (
offerOnlyQueue: Queue.Enqueue<number>
offerOnlyQueue
:
import Queue
Queue
.
interface Enqueue<in A>

@since2.0.0

Enqueue
<number>,
value: number
value
: number) => {
// 此队列仅限于提供操作
// 错误:不能在仅提供队列上使用 take
import Queue
Queue
.
const take: <unknown>(self: Queue.Dequeue<unknown>) => Effect<unknown, never, never>

Takes the oldest value in the queue. If the queue is empty, this will return a computation that resumes when an item has been added to the queue.

@since2.0.0

take
(offerOnlyQueue)
Error ts(2345) ― Argument of type 'Enqueue<number>' is not assignable to parameter of type 'Dequeue<unknown>'. Type 'Enqueue<number>' is missing the following properties from type 'Dequeue<unknown>': take, takeAll, takeUpTo, takeBetween, and 6 more.
// 有效的提供操作
return
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
offerOnlyQueue: Queue.Enqueue<number>
offerOnlyQueue
,
value: number
value
)
}

类似地,从队列检索值的所有方法都由 Dequeue 接口定义,该接口将队列限制为仅取操作。

示例(将队列限制为仅取操作)

import {
import Queue
Queue
} from "effect"
const
const receive: (takeOnlyQueue: Queue.Dequeue<number>) => Effect<number, never, never>
receive
= (
takeOnlyQueue: Queue.Dequeue<number>
takeOnlyQueue
:
import Queue
Queue
.
interface Dequeue<out A>

@since2.0.0

Dequeue
<number>) => {
// 此队列仅限于取操作
// 错误:不能在仅取队列上使用 offer
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(takeOnlyQueue, 1)
Error ts(2345) ― Argument of type 'Dequeue<number>' is not assignable to parameter of type 'Enqueue<number>'. Type 'Dequeue<number>' is missing the following properties from type 'Enqueue<number>': offer, unsafeOffer, offerAll, [EnqueueTypeId]
// 有效的取操作
return
import Queue
Queue
.
const take: <number>(self: Queue.Dequeue<number>) => Effect<number, never, never>

Takes the oldest value in the queue. If the queue is empty, this will return a computation that resumes when an item has been added to the queue.

@since2.0.0

take
(
takeOnlyQueue: Queue.Dequeue<number>
takeOnlyQueue
)
}

The Queue 类型结合了 EnqueueDequeue,因此您可以轻松地将其传递给代码的不同部分,根据需要仅强制执行 EnqueueDequeue 行为。

示例(一起使用仅提供和仅取队列)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Queue
Queue
} from "effect"
const
const send: (offerOnlyQueue: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean, never, never>
send
= (
offerOnlyQueue: Queue.Enqueue<number>
offerOnlyQueue
:
import Queue
Queue
.
interface Enqueue<in A>

@since2.0.0

Enqueue
<number>,
value: number
value
: number) => {
return
import Queue
Queue
.
const offer: <number>(self: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean> (+1 overload)

Places one value in the queue.

@since2.0.0

offer
(
offerOnlyQueue: Queue.Enqueue<number>
offerOnlyQueue
,
value: number
value
)
}
const
const receive: (takeOnlyQueue: Queue.Dequeue<number>) => Effect.Effect<number, never, never>
receive
= (
takeOnlyQueue: Queue.Dequeue<number>
takeOnlyQueue
:
import Queue
Queue
.
interface Dequeue<out A>

@since2.0.0

Dequeue
<number>) => {
return
import Queue
Queue
.
const take: <number>(self: Queue.Dequeue<number>) => Effect.Effect<number, never, never>

Takes the oldest value in the queue. If the queue is empty, this will return a computation that resumes when an item has been added to the queue.

@since2.0.0

take
(
takeOnlyQueue: Queue.Dequeue<number>
takeOnlyQueue
)
}
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>> | YieldWrap<Effect.Effect<number, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<Queue.Queue<number>, never, never>> | YieldWrap<Effect.Effect<boolean, never, never>> | YieldWrap<Effect.Effect<number, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const queue: Queue.Queue<number>
queue
= yield*
import Queue
Queue
.
const unbounded: <number>() => Effect.Effect<Queue.Queue<number>, never, never>

Creates a new unbounded Queue.

@since2.0.0

unbounded
<number>()
// 向队列添加值
yield*
const send: (offerOnlyQueue: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean, never, never>
send
(
const queue: Queue.Queue<number>
queue
, 1)
yield*
const send: (offerOnlyQueue: Queue.Enqueue<number>, value: number) => Effect.Effect<boolean, never, never>
send
(
const queue: Queue.Queue<number>
queue
, 2)
// 从队列检索值
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(yield*
const receive: (takeOnlyQueue: Queue.Dequeue<number>) => Effect.Effect<number, never, never>
receive
(
const queue: Queue.Queue<number>
queue
))
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(yield*
const receive: (takeOnlyQueue: Queue.Dequeue<number>) => Effect.Effect<number, never, never>
receive
(
const queue: Queue.Queue<number>
queue
))
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runFork: <void, never>(effect: Effect.Effect<void, never, never>, options?: RunForkOptions) => RuntimeFiber<void, never>

Runs an effect in the background, returning a fiber that can be observed or interrupted.

Unless you specifically need a Promise or synchronous operation, runFork is a good default choice.

Details

This function is the foundational way to execute an effect in the background. It creates a "fiber," a lightweight, cooperative thread of execution that can be observed (to access its result), interrupted, or joined. Fibers are useful for concurrent programming and allow effects to run independently of the main program flow.

Once the effect is running in a fiber, you can monitor its progress, cancel it if necessary, or retrieve its result when it completes. If the effect fails, the fiber will propagate the failure, which you can observe and handle.

When to Use

Use this function when you need to run an effect in the background, especially if the effect is long-running or performs periodic tasks. It's suitable for tasks that need to run independently but might still need observation or management, like logging, monitoring, or scheduled tasks.

This function is ideal if you don't need the result immediately or if the effect is part of a larger concurrent workflow.

Example (Running an Effect in the Background)

import { Effect, Console, Schedule, Fiber } from "effect"
// ┌─── Effect<number, never, never>
// ▼
const program = Effect.repeat(
Console.log("running..."),
Schedule.spaced("200 millis")
)
// ┌─── RuntimeFiber<number, never>
// ▼
const fiber = Effect.runFork(program)
setTimeout(() => {
Effect.runFork(Fiber.interrupt(fiber))
}, 500)

@since2.0.0

runFork
(
const program: Effect.Effect<void, never, never>
program
)
/*
输出:
1
2
*/