Repetition
On this page
Repetition is a common requirement when working with effects in software development. It allows us to perform an effect multiple times according to a specific repetition policy.
repeat
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 Effect.repeat(action, Schedule.once)
executes action
once initially, and if it succeeds, repeats it an additional time.
Success Example
ts
import {Effect ,Schedule ,Console } from "effect"constaction =Console .log ("success")constpolicy =Schedule .addDelay (Schedule .recurs (2), () => "100 millis")constprogram =Effect .repeat (action ,policy )Effect .runPromise (program ).then ((n ) =>console .log (`repetitions: ${n }`))/*Output:successsuccesssuccessrepetitions: 2*/
ts
import {Effect ,Schedule ,Console } from "effect"constaction =Console .log ("success")constpolicy =Schedule .addDelay (Schedule .recurs (2), () => "100 millis")constprogram =Effect .repeat (action ,policy )Effect .runPromise (program ).then ((n ) =>console .log (`repetitions: ${n }`))/*Output:successsuccesssuccessrepetitions: 2*/
Failure Example
ts
import {Effect ,Schedule } from "effect"letcount = 0// Define an async effect that simulates an action with possible failuresconstaction =Effect .async <string, string>((resume ) => {if (count > 1) {console .log ("failure")resume (Effect .fail ("Uh oh!"))} else {count ++console .log ("success")resume (Effect .succeed ("yay!"))}})constpolicy =Schedule .addDelay (Schedule .recurs (2), () => "100 millis")constprogram =Effect .repeat (action ,policy )Effect .runPromiseExit (program ).then (console .log )/*Output:successsuccessfailure{_id: 'Exit',_tag: 'Failure',cause: { _id: 'Cause', _tag: 'Fail', failure: 'Uh oh!' }}*/
ts
import {Effect ,Schedule } from "effect"letcount = 0// Define an async effect that simulates an action with possible failuresconstaction =Effect .async <string, string>((resume ) => {if (count > 1) {console .log ("failure")resume (Effect .fail ("Uh oh!"))} else {count ++console .log ("success")resume (Effect .succeed ("yay!"))}})constpolicy =Schedule .addDelay (Schedule .recurs (2), () => "100 millis")constprogram =Effect .repeat (action ,policy )Effect .runPromiseExit (program ).then (console .log )/*Output:successsuccessfailure{_id: 'Exit',_tag: 'Failure',cause: { _id: 'Cause', _tag: 'Fail', failure: 'Uh oh!' }}*/
Skipping the First Occurrence
If you want to skip the first occurrence of a repeat, you can use Effect.schedule
:
ts
import {Effect ,Schedule ,Console } from "effect"constaction =Console .log ("success")constpolicy =Schedule .addDelay (Schedule .recurs (2), () => "100 millis")constprogram =Effect .schedule (action ,policy )Effect .runPromise (program ).then ((n ) =>console .log (`repetitions: ${n }`))/*Output:successsuccessrepetitions: 2*/
ts
import {Effect ,Schedule ,Console } from "effect"constaction =Console .log ("success")constpolicy =Schedule .addDelay (Schedule .recurs (2), () => "100 millis")constprogram =Effect .schedule (action ,policy )Effect .runPromise (program ).then ((n ) =>console .log (`repetitions: ${n }`))/*Output:successsuccessrepetitions: 2*/
repeatN
The repeatN
function returns a new effect that repeats the specified effect a given number of times or until the first failure. The repeats are in addition to the initial execution, so Effect.repeatN(action, 1)
executes action
once initially and then repeats it one additional time if it succeeds.
ts
import {Effect ,Console } from "effect"constaction =Console .log ("success")constprogram =Effect .repeatN (action , 2)Effect .runPromise (program )/*Output:successsuccesssuccess*/
ts
import {Effect ,Console } from "effect"constaction =Console .log ("success")constprogram =Effect .repeatN (action , 2)Effect .runPromise (program )/*Output:successsuccesssuccess*/
repeatOrElse
The repeatOrElse
function returns a new effect that repeats the specified effect according to the given schedule or until the first failure. When a failure occurs, the failure value and schedule output are passed to a specified handler. Scheduled recurrences are in addition to the initial execution, so Effect.repeat(action, Schedule.once)
executes action
once initially and then repeats it an additional time if it succeeds.
ts
import {Effect ,Schedule } from "effect"letcount = 0// Define an async effect that simulates an action with possible failuresconstaction =Effect .async <string, string>((resume ) => {if (count > 1) {console .log ("failure")resume (Effect .fail ("Uh oh!"))} else {count ++console .log ("success")resume (Effect .succeed ("yay!"))}})constpolicy =Schedule .addDelay (Schedule .recurs (2), // Repeat for a maximum of 2 times() => "100 millis" // Add a delay of 100 milliseconds between repetitions)constprogram =Effect .repeatOrElse (action ,policy , () =>Effect .sync (() => {console .log ("orElse")returncount - 1}))Effect .runPromise (program ).then ((n ) =>console .log (`repetitions: ${n }`))/*Output:successsuccessfailureorElserepetitions: 1*/
ts
import {Effect ,Schedule } from "effect"letcount = 0// Define an async effect that simulates an action with possible failuresconstaction =Effect .async <string, string>((resume ) => {if (count > 1) {console .log ("failure")resume (Effect .fail ("Uh oh!"))} else {count ++console .log ("success")resume (Effect .succeed ("yay!"))}})constpolicy =Schedule .addDelay (Schedule .recurs (2), // Repeat for a maximum of 2 times() => "100 millis" // Add a delay of 100 milliseconds between repetitions)constprogram =Effect .repeatOrElse (action ,policy , () =>Effect .sync (() => {console .log ("orElse")returncount - 1}))Effect .runPromise (program ).then ((n ) =>console .log (`repetitions: ${n }`))/*Output:successsuccessfailureorElserepetitions: 1*/