フォールバック
orElse
一つの Effect を試み、失敗した場合にはEffect.orElseコンビネータを使って別の Effect を試すことができます。
import { Effect } from "effect";
const success = Effect.succeed("成功");const failure = Effect.fail("失敗");const fallback = Effect.succeed("フォールバック");
const program1 = Effect.orElse(success, () => fallback);console.log(Effect.runSync(program1)); // 出力: "成功"
const program2 = Effect.orElse(failure, () => fallback);console.log(Effect.runSync(program2)); // 出力: "フォールバック"orElseFail / orElseSucceed
これらの二つのオペレーターは、元の失敗を定数の成功または失敗の値で置き換えます。
Effect.orElseFailは常に元の失敗を新しいものに置き換えます:
import { Effect } from "effect"
class NegativeAgeError { readonly _tag = "NegativeAgeError" constructor(readonly age: number) {}}
class IllegalAgeError { readonly _tag = "IllegalAgeError" constructor(readonly age: number) {}}
const validate = ( age: number): Effect.Effect<number, NegativeAgeError | IllegalAgeError> => { if (age < 0) { return Effect.fail(new NegativeAgeError(age)) } else if (age < 18) { return Effect.fail(new IllegalAgeError(age)) } else { return Effect.succeed(age) }}// @include: validate
const program1 = Effect.orElseFail(validate(3), () => "無効な年齢");Effect.orElseSucceed関数は常に元の失敗を成功の値で置き換えるため、結果として得られる Effect は失敗することがありません:
// @include: validate// ---cut---const program2 = Effect.orElseSucceed(validate(3), () => 0);firstSuccessOf
firstSuccessOfオペレーターは一連の Effect を実行する簡易的な方法を提供し、最初の成功した Effect の結果を返します。どの Effect も成功しなかった場合、結果の Effect は系列の最後の Effect のエラーで失敗します。
このオペレーターはEffect.orElseを利用して複数の Effect を一つの Effect に結合します。
以下の例では、異なるノードから設定を取得しようとしています。プライマリノードからの取得が失敗した場合、次に利用可能なノードから取得し、成功する結果が得られるまで試みます:
import { Effect, Console } from "effect";
interface Config { // ...}
const makeConfig = (/* ... */): Config => ({});
const remoteConfig = (name: string): Effect.Effect<Config, Error> => Effect.gen(function* () { if (name === "node3") { yield* Console.log(`ノード ${name} の設定が見つかりました`); return makeConfig(); } else { yield* Console.log(`ノード ${name} の設定は利用できません`); return yield* Effect.fail(new Error()); } });
const masterConfig = remoteConfig("master");
const nodeConfigs = ["node1", "node2", "node3", "node4"].map(remoteConfig);
const config = Effect.firstSuccessOf([masterConfig, ...nodeConfigs]);
console.log(Effect.runSync(config));/*出力:ノード master の設定は利用できませんノード node1 の設定は利用できませんノード node2 の設定は利用できませんノード node3 の設定が見つかりました{}*/