Skip to content

繰り返し

繰り返しは、ソフトウェア開発における Effect の操作において一般的な要件です。特定の繰り返しポリシーに従って、効果を複数回実行することを可能にします。

repeat

Effect.repeat関数は、指定されたスケジュールに従って、または最初の失敗まで、与えられた効果を繰り返す新しい Effect を返します。

成功の例

import { Effect, Schedule, Console } from "effect";
const action = Console.log("success");
const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis");
const program = Effect.repeat(action, policy);
Effect.runPromise(program).then((n) => console.log(`repetitions: ${n}`));
/*
出力:
success
success
success
repetitions: 2
*/

失敗の例

import { Effect, Schedule } from "effect";
let count = 0;
// 可能な失敗をシミュレートする非同期のEffectを定義します
const action = Effect.async<string, string>((resume) => {
if (count > 1) {
console.log("failure");
resume(Effect.fail("うわっ!"));
} else {
count++;
console.log("success");
resume(Effect.succeed("やった!"));
}
});
const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis");
const program = Effect.repeat(action, policy);
Effect.runPromiseExit(program).then(console.log);
/*
出力:
success
success
failure
{
_id: 'Exit',
_tag: 'Failure',
cause: { _id: 'Cause', _tag: 'Fail', failure: 'うわっ!' }
}
*/

最初の発生をスキップする

最初の発生をスキップしたい場合は、Effect.scheduleを使用できます:

import { Effect, Schedule, Console } from "effect";
const action = Console.log("success");
const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis");
const program = Effect.schedule(action, policy);
Effect.runPromise(program).then((n) => console.log(`repetitions: ${n}`));
/*
出力:
success
success
repetitions: 2
*/

repeatN

repeatN関数は、指定された効果を指定した回数だけ繰り返す新しい Effect を返します。繰り返しは初回の実行に加算されるため、Effect.repeatN(action, 1)は最初にactionを 1 回実行し、その後成功した場合に追加で 1 回繰り返します。

import { Effect, Console } from "effect";
const action = Console.log("success");
const program = Effect.repeatN(action, 2);
Effect.runPromise(program);
/*
出力:
success
success
success
*/

repeatOrElse

repeatOrElse関数は、指定されたスケジュールに従って効果を繰り返す新しい Effect を返します。失敗が発生した場合、失敗値とスケジュールの出力が指定されたハンドラに渡されます。スケジュールされた繰り返しは初回の実行に加算されるため、Effect.repeat(action, Schedule.once)は最初にactionを 1 回実行し、その後成功した場合に追加で 1 回繰り返します。

import { Effect, Schedule } from "effect";
let count = 0;
// 可能な失敗をシミュレートする非同期のEffectを定義します
const action = Effect.async<string, string>((resume) => {
if (count > 1) {
console.log("failure");
resume(Effect.fail("うわっ!"));
} else {
count++;
console.log("success");
resume(Effect.succeed("やった!"));
}
});
const policy = Schedule.addDelay(
Schedule.recurs(2), // 最大2回繰り返す
() => "100 millis" // 繰り返しの間に100ミリ秒の遅延を追加
);
const program = Effect.repeatOrElse(action, policy, () =>
Effect.sync(() => {
console.log("orElse");
return count - 1;
})
);
Effect.runPromise(program).then((n) => console.log(`repetitions: ${n}`));
/*
出力:
success
success
failure
orElse
repetitions: 1
*/

条件に基づいて繰り返し

条件を使用して Effect の繰り返しを制御することができます。whileまたはuntilオプションを使用し、ランタイムの結果に基づいて動的に制御することが可能です。

import { Effect } from "effect";
let count = 0;
// 各呼び出し時に異なる結果をシミュレートするEffectを定義します
const action = Effect.sync(() => {
console.log(`Action called ${++count}`);
return count;
});
// 特定の条件が満たされるまでアクションを繰り返します
const program = Effect.repeat(action, { until: (n) => n === 3 });
Effect.runFork(program);
/*
出力:
Action called 1 回
Action called 2 回
Action called 3 回
*/

エラーに基づいて条件を設定するには、Effect.retryの使用を検討してください。