runPromise - Promise-Based Execution
import { Effect } from "effect"
class ApiError {
readonly _tag = "ApiError"
constructor(readonly status: number) {}
}
const failing = Effect.fail(new ApiError(404))
Effect.runPromise(failing)
.catch((error) => {
console.error(error) // ApiError { _tag: 'ApiError', status: 404 }
})
import { Effect } from "effect"
const longRunning = Effect.gen(function* () {
yield* Effect.sleep("10 seconds")
return "Done!"
})
const controller = new AbortController()
Effect.runPromise(longRunning, { signal: controller.signal })
.catch((error) => console.log("Cancelled!"))
// Cancel after 1 second
setTimeout(() => controller.abort(), 1000)
runPromise requires the effect to have no dependencies (R = never). Provide all services before calling runPromise.import { Effect, Context } from "effect"
class Database extends Context.Tag("Database")<
Database,
{ query: (sql: string) => Effect.Effect<unknown> }
>() {}
const program = Database.pipe(
Effect.flatMap((db) => db.query("SELECT * FROM users"))
)
// Effect<unknown, never, Database>
// ❌ Type error: R is not never
// Effect.runPromise(program)
// ✅ Provide dependencies first
const testDatabase = Database.of({
query: (sql) => Effect.succeed([{ id: 1, name: "Alice" }])
})
Effect.runPromise(
program.pipe(Effect.provideService(Database, testDatabase))
)
runPromiseExit - Structured Results
Use
runPromiseExit when you need structured error information or want to avoid try/catch blocks.runSync - Synchronous Execution
import { Effect } from "effect"
const asyncProgram = Effect.gen(function* () {
yield* Effect.sleep("100 millis")
return 42
})
// ❌ Throws: AsyncFiberException
// Effect.runSync(asyncProgram)
// ✅ Use runPromise for async effects
await Effect.runPromise(asyncProgram) // 42
runSyncExit - Synchronous with Exit
Runtime - Advanced Execution
A Runtime encapsulates the context, flags, and fiber refs needed to run effects:interface Runtime<R> {
readonly context: Context.Context<R>
readonly runtimeFlags: RuntimeFlags.RuntimeFlags
readonly fiberRefs: FiberRefs.FiberRefs
}
import { Effect, Runtime } from "effect"
const runtime = Runtime.defaultRuntime
const fiber = Runtime.runFork(runtime, Effect.succeed(42))
const result = await fiber.await
import { Effect, Runtime } from "effect"
const result = Runtime.runSync(
Runtime.defaultRuntime,
Effect.succeed(42)
)
import { Effect, Runtime } from "effect"
const result = await Runtime.runPromise(
Runtime.defaultRuntime,
Effect.succeed(42)
)
import { Effect } from "effect"
// These are equivalent:
Effect.runPromise(program)
Runtime.runPromise(Runtime.defaultRuntime, program)
import { Effect, Runtime, Context } from "effect"
class Database extends Context.Tag("Database")<
Database,
{ query: (sql: string) => Effect.Effect<unknown> }
>() {}
// Production runtime
const prodRuntime = Runtime.make({
context: Context.make(Database, {
query: (sql) => Effect.tryPromise(() => db.execute(sql))
})
})
// Test runtime with mock
const testRuntime = Runtime.make({
context: Context.make(Database, {
query: (sql) => Effect.succeed([{ id: 1, name: "Test" }])
})
})
const program = Database.pipe(
Effect.flatMap((db) => db.query("SELECT * FROM users"))
)
// Use different runtimes
await Runtime.runPromise(prodRuntime, program) // Real DB
await Runtime.runPromise(testRuntime, program) // Mock
runFork - Fiber-Based Execution
Comparison Table
| Method | Returns | Async Support | Error Handling | Use Case |
|---|---|---|---|---|
runPromise | Promise<A> | ✅ | Rejects | Async effects, integrating with promises |
runPromiseExit | Promise<Exit<A, E>> | ✅ | Structured | Need detailed error info |
runSync | A | ❌ | Throws | Sync-only effects, testing |
runSyncExit | Exit<A, E> | ❌ | Structured | Sync effects with error info |
runFork | Fiber<A, E> | ✅ | Via fiber | Background execution, cancellation |
Best Practices
// ❌ Bad: Running effects in the middle of your program
function processUser(id: number) {
const user = Effect.runSync(fetchUser(id))
return user
}
// ✅ Good: Return effects and compose them
function processUser(id: number): Effect.Effect<User, Error> {
return fetchUser(id)
}
// Run only at application boundary
const main = processUser(1)
Effect.runPromise(main)
import { Effect } from "effect"
const program: Effect.Effect<Result, Error, Database | Logger> = ...
// ❌ Type error: still has dependencies
// Effect.runPromise(program)
// ✅ Provide all services first
Effect.runPromise(
program.pipe(
Effect.provideService(Database, dbImpl),
Effect.provideService(Logger, loggerImpl)
)
)