When making API calls to third-party services, we may want to enforce timeouts and retry mechanisms.
In this example, the API call is set to retry a maximum of two times in case of failure, and the entire operation will be interrupted if it takes longer than 4 seconds.
Implementing Conditional Retries
Sometimes, we need to retry a failed API call only for specific error conditions, such as certain HTTP status codes.
Creates an Effect that represents an asynchronous computation that might
fail.
When to Use
In situations where you need to perform asynchronous operations that might
fail, such as fetching data from an API, you can use the tryPromise
constructor. This constructor is designed to handle operations that could
throw exceptions by capturing those exceptions and transforming them into
manageable errors.
Error Handling
There are two ways to handle errors with tryPromise:
If you don't provide a catch function, the error is caught and the
effect fails with an UnknownException.
If you provide a catch function, the error is caught and the catch
function maps it to an error of type E.
Interruptions
An optional AbortSignal can be provided to allow for interruption of the
wrapped Promise API.
@see ― promise if the effectful computation is asynchronous and does not throw errors.
@example
// Title: Fetching a TODO Item
import { Effect } from"effect"
constgetTodo= (id:number) =>
// Will catch any errors and propagate them as UnknownException
Attaches callbacks for the resolution and/or rejection of the Promise.
@param ― onfulfilled The callback to execute when the Promise is resolved.
@param ― onrejected The callback to execute when the Promise is rejected.
@returns ― A Promise for the completion of which ever callback is executed.
then((
res: Response
res) => {
15
if (!
res: Response
res.
Response.ok: boolean
ok) {
16
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(newError('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
constname='Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
Example using the Console class:
constout=getStreamSomehow();
consterr=getStreamSomehow();
constmyConsole=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(newError('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
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()).
Retries a failing effect based on a defined retry policy.
Details
The Effect.retry function takes an effect and a
Schedule
policy,
and will automatically retry the effect if it fails, following the rules of
the policy.
If the effect ultimately succeeds, the result will be returned.
If the maximum retries are exhausted and the effect still fails, the failure
is propagated.
When to Use
This can be useful when dealing with intermittent failures, such as network
issues or temporary resource unavailability. By defining a retry policy, you
can control the number of retries, the delay between them, and when to stop
retrying.
@see ― retryOrElse for a version that allows you to run a fallback.
@see ― repeat if your retry condition is based on successful outcomes rather than errors.
Handles all errors in an effect by providing a fallback effect.
Details
This function catches any errors that may occur during the execution of an
effect and allows you to handle them by specifying a fallback effect. This
ensures that the program continues without failing by recovering from errors
using the provided fallback logic.
Note: This function only handles recoverable errors. It will not recover
from unrecoverable defects.
@see ― catchAllCause for a version that can recover from both
recoverable and unrecoverable errors.
@example
// Title: Providing Recovery Logic for Recoverable Errors
The foundational function for running effects, returning a "fiber" that can
be observed or interrupted.
When to Use
runFork is used to run an effect in the background by creating a
fiber. It is the base function for all other run functions. It starts a fiber
that can be observed or interrupted.
Unless you specifically need a Promise or synchronous operation,
runFork is a good default choice.
The foundational function for running effects, returning a "fiber" that can
be observed or interrupted.
When to Use
runFork is used to run an effect in the background by creating a
fiber. It is the base function for all other run functions. It starts a fiber
that can be observed or interrupted.
Unless you specifically need a Promise or synchronous operation,
runFork is a good default choice.
Sometimes, we need to run a task periodically until a longer-running task completes. This is common in scenarios like polling or periodic status logging.
Races two effects and returns the result of the first successful one.
Details
This function takes two effects and runs them concurrently. The first effect
that successfully completes will determine the result of the race, and the
other effect will be interrupted.
If neither effect succeeds, the function will fail with a Cause
containing all the errors.
When to Use
This is useful when you want to run two effects concurrently, but only care
about the first one to succeed. It is commonly used in cases like timeouts,
retries, or when you want to optimize for the faster response without
worrying about the other effect.
Handling Success or Failure with Either
If you want to handle the result of whichever task completes first, whether
it succeeds or fails, you can use the Effect.either function. This function
wraps the result in an Either type, allowing you to see if the result
was a success (Right) or a failure (Left).
@see ― raceAll for a version that handles multiple effects.
@see ― raceFirst for a version that returns the result of the first effect to complete.
The repeat function returns a new effect that repeats the given effect
according to a specified schedule or until the first failure. The scheduled
recurrences are in addition to the initial execution, so repeat(action, Schedule.once) executes action once initially, and if it succeeds, repeats it
an additional time.
Executes an effect and returns the result as a Promise.
When to Use
Use runPromise when you need to execute an effect and work with the
result using Promise syntax, typically for compatibility with other
promise-based code.
If the effect succeeds, the promise will resolve with the result. If the
effect fails, the promise will reject with an error.
@see ― runPromiseExit for a version that returns an Exit type instead of rejecting.
@example
// Title: Running a Successful Effect as a Promise