Layer memoization allows a layer to be created once and used multiple times in the dependency graph. If we use the same layer twice:
then the L1 layer will be allocated only once.
Memoization When Providing Globally
One important feature of an Effect application is that layers are shared by default. This means that if the same layer is used twice, and if we provide the layer globally, the layer will only be allocated a single time. For every layer in our dependency graph, there is only one instance of it that is shared between all the layers that depend on it.
Example
For example, assume we have the three services A, B, and C. The implementation of both B and C is dependent on the A service:
Although both BLive and CLive layers require the ALive layer, the ALive layer is instantiated only once. It is shared with both BLive and CLive.
Acquiring a Fresh Version
If we don’t want to share a module, we should create a fresh, non-shared version of it through Layer.fresh.
Creates an Effect that succeeds with the provided value.
Use this function to represent a successful computation that yields a value of type A.
The effect does not fail and does not require any environmental context.
@example
import { Effect } from "effect"
// Creating an effect that succeeds with the number 42
const success = Effect.succeed(42)
Logs one or more messages or error causes at the current log level, which is INFO by default.
This function allows logging multiple items at once and can include detailed error information using Cause instances.
To adjust the log level, use the Logger.withMinimumLogLevel function.
Feeds the output services of this builder into the input of the specified
builder, resulting in a new builder with the inputs of this builder as
well as any leftover inputs, and the outputs of the specified builder.
Feeds the output services of this builder into the input of the specified
builder, resulting in a new builder with the inputs of this builder as
well as any leftover inputs, and the outputs of the specified builder.
Executes an effect and returns a Promise that resolves with the result.
Use runPromise when working with asynchronous effects and you need to integrate with code that uses Promises.
If the effect fails, the returned Promise will be rejected with the error.
@example
import { Effect } from "effect"
// Execute an effect and handle the result with a Promise
Effect.runPromise(Effect.succeed(1)).then(console.log) // Output: 1
// Execute a failing effect and handle the rejection
Effect.runPromise(Effect.fail("my error")).catch((error) => {
console.error("Effect failed with error:", error)
})
If we don’t provide a layer globally but instead provide them locally, that layer doesn’t support memoization by default.
Example
In the following example, we provided the ALive layer two times locally, and Effect doesn’t memoize the construction of the ALive layer.
So, it will be initialized two times:
Creates an Effect that succeeds with the provided value.
Use this function to represent a successful computation that yields a value of type A.
The effect does not fail and does not require any environmental context.
@example
import { Effect } from "effect"
// Creating an effect that succeeds with the number 42
const success = Effect.succeed(42)
Logs one or more messages or error causes at the current log level, which is INFO by default.
This function allows logging multiple items at once and can include detailed error information using Cause instances.
To adjust the log level, use the Logger.withMinimumLogLevel function.
Executes an effect and returns a Promise that resolves with the result.
Use runPromise when working with asynchronous effects and you need to integrate with code that uses Promises.
If the effect fails, the returned Promise will be rejected with the error.
@example
import { Effect } from "effect"
// Execute an effect and handle the result with a Promise
Effect.runPromise(Effect.succeed(1)).then(console.log) // Output: 1
// Execute a failing effect and handle the rejection
Effect.runPromise(Effect.fail("my error")).catch((error) => {
console.error("Effect failed with error:", error)
})
We can memoize a layer manually using the Layer.memoize function.
It will return a scoped effect that, if evaluated, will return the lazily computed result of this layer.
Creates an Effect that succeeds with the provided value.
Use this function to represent a successful computation that yields a value of type A.
The effect does not fail and does not require any environmental context.
@example
import { Effect } from "effect"
// Creating an effect that succeeds with the number 42
const success = Effect.succeed(42)
Logs one or more messages or error causes at the current log level, which is INFO by default.
This function allows logging multiple items at once and can include detailed error information using Cause instances.
To adjust the log level, use the Logger.withMinimumLogLevel function.
Scopes all resources used in this workflow to the lifetime of the workflow,
ensuring that their finalizers are run as soon as this workflow completes
execution, whether by success, failure, or interruption.
Executes an effect and returns a Promise that resolves with the result.
Use runPromise when working with asynchronous effects and you need to integrate with code that uses Promises.
If the effect fails, the returned Promise will be rejected with the error.
@example
import { Effect } from "effect"
// Execute an effect and handle the result with a Promise
Effect.runPromise(Effect.succeed(1)).then(console.log) // Output: 1
// Execute a failing effect and handle the rejection
Effect.runPromise(Effect.fail("my error")).catch((error) => {
console.error("Effect failed with error:", error)
})