HttpClient.filterOrElse() is the recovery-oriented counterpart to filterOrFail. Instead of producing an error when the predicate fails, it runs an alternative effect that can return a different response.
This is useful when you want to transparently handle certain response conditions, like falling back to a cached response, retrying with different parameters, or transforming an unexpected response into an expected one.
import { FetchHttpClient, HttpClient, HttpClientRequest,} from "effect/unstable/http";import { Effect } from "effect";
function fetchProductWithFallback(productId: number) { return Effect.gen(function* () { const client = (yield* HttpClient.HttpClient).pipe( // If the response isn't a 200, fall back to product 1 HttpClient.filterOrElse( (response) => response.status === 200, (response) => Effect.gen(function* () { console.log( `Got status ${response.status}, falling back to product 1`, ); const fallbackClient = yield* HttpClient.HttpClient; return yield* fallbackClient.get( "https://dummyjson.com/products/1", ); }), ), );
const request = HttpClientRequest.get( `https://dummyjson.com/products/${productId}`, );
const response = yield* client.execute(request); const product = yield* response.json;
return product; }).pipe(Effect.provide(FetchHttpClient.layer));}
// Test with a valid productEffect.runPromise(fetchProductWithFallback(1)).then((product) => { console.log("Product:", product.title);});
// Test with an invalid product — falls back to product 1Effect.runPromise(fetchProductWithFallback(99999)).then((product) => { console.log("Product:", product.title);});Output:
Product: Essence Mascara Lash PrincessGot status 404, falling back to product 1Product: Essence Mascara Lash PrincessThe first argument is the same predicate as filterOrFail. The difference is the second argument: instead of an error constructor, it’s a function that returns an Effect<HttpClientResponse>. This effect can do anything: make another request, return a cached response, or even succeed with the original response after logging.
The key distinction between the two:
filterOrFail: Predicate fails → error in the error channel. The caller must handle it.filterOrElse: Predicate fails → alternative effect runs. The caller doesn’t know the filter was triggered.
Use filterOrFail when a bad response is an error your application needs to know about. Use filterOrElse when you can transparently recover and the caller doesn’t need to care.