| title | Creating from Synchronous and Callback Code | |||||||
|---|---|---|---|---|---|---|---|---|
| id | constructor-sync-async | |||||||
| skillLevel | beginner | |||||||
| applicationPatternId | core-concepts | |||||||
| summary | Use sync and async to lift synchronous or callback-based computations into Effect, enabling safe and composable interop with legacy code. | |||||||
| tags |
|
|||||||
| rule |
|
|||||||
| related |
|
|||||||
| author | PaulJPhilp | |||||||
| lessonOrder | 10 |
Use the sync and async constructors to lift synchronous or callback-based computations into the Effect world.
This enables safe, composable interop with legacy or third-party code that doesn't use Promises or Effects.
Many APIs are synchronous or use callbacks instead of Promises.
By lifting them into Effects, you gain access to all of Effect's combinators, error handling, and resource safety.
import { Effect } from "effect";
// Synchronous: Wrap a computation that is guaranteed not to throw
const effectSync = Effect.sync(() => Math.random()); // Effect<never, number, never>
// Callback-based: Wrap a Node.js-style callback API
function legacyReadFile(
path: string,
cb: (err: Error | null, data?: string) => void
) {
setTimeout(() => cb(null, "file contents"), 10);
}
const effectAsync = Effect.async<string, Error>((resume) => {
legacyReadFile("file.txt", (err, data) => {
if (err) resume(Effect.fail(err));
else resume(Effect.succeed(data!));
});
}); // Effect<string, Error, never>Explanation:
Effect.syncis for synchronous computations that are guaranteed not to throw.Effect.asyncis for integrating callback-based APIs, converting them into Effects.
Directly calling synchronous or callback-based APIs inside Effects without lifting them, which can break composability and error handling.