NAME
Fetch::Future - a fast, native, Future-compatible async result
SYNOPSIS
my $f = Fetch::Future->new;
$f->on_done(sub { my $v = shift; ... });
$f->done(42);
my $all = Fetch::Future->needs_all($f1, $f2);
my @v = $f->get; # pumps the active loop (or Standalone) until ready
DESCRIPTION
An asynchronous result with an API compatible with CPAN Future: done/fail/cancel, on_ready/on_done/on_fail/on_cancel, then/else/followed_by/transform, get/await, and the convergent combinators wait_all/wait_any/needs_all/needs_any.
The implementation is entirely XS over an array-slot object; continuations are C closures trampolined through a fire queue, so long then-chains run iteratively with bounded stack depth.
get/await on a pending future pump the current event loop re-entrantly. Outside a running loop, an external loop may install $Fetch::Future::AWAIT (a coderef receiving the future) to make awaiting work.
as_cpan_future / from_future convert to and from CPAN Future objects for interop with isa('Future') code.
CONSTRUCTORS
new
my $f = Fetch::Future->new;
A new pending future.
done_future(@values) / fail_future(@failure)
my $f = Fetch::Future->done_future(42);
my $f = Fetch::Future->fail_future("nope\n");
An already-resolved future, done with @values or failed with @failure.
RESOLVING
done(@values)
Mark a pending future done with @values; fires its ready/done callbacks. Returns the future.
fail($message, @details)
Mark a pending future failed. Returns the future.
cancel
Cancel a pending future.
STATE
is_ready / is_done / is_failed / is_cancelled
Booleans: whether the future has settled at all, and how.
CALLBACKS
on_ready($cb)
Call $cb->($future) when the future settles (done, failed or cancelled). Returns the future.
on_done($cb) / on_fail($cb)
Call $cb->(@values) on success, or $cb->(@failure) on failure. Return the future.
on_cancel($cb) / on_cancel($future)
Given a coderef, call $cb->($future) when this future is cancelled; given another future, cancel that one with it. Registering on a future that has already been cancelled runs the target at once. Registering on one that completed normally drops it, because that future will never cancel. Returns the future.
CHAINING
Each returns a new future and flattens a future returned by the callback, so long chains compose without nesting.
then($on_done) / then($on_done, $on_fail)
Run $on_done with the values when this future succeeds; its result (a value list or a future) becomes the new future's result. Failure passes through unless $on_fail is given.
else($on_fail)
Like then but for the failure branch.
followed_by($cb)
Call $cb->($future) once this future settles either way, and adopt the future it returns.
transform(done => $cb, fail => $cb)
Map the done values and/or failure through the given coderefs.
AWAITING
get / result
my @values = $f->get; # or a scalar in scalar context
Block until the future is ready, pumping the active event loop (the Standalone loop if none), then return its values - or rethrow its failure.
await
Block until ready (pumping the loop) and return the future itself.
failure
The failure of a failed future (the first failure value), or undef.
COMBINATORS
Each takes a list of futures and returns one future.
needs_all(@futures)
Done when all succeed (with their combined values); fails as soon as any fails.
needs_any(@futures)
Done as soon as any succeeds; fails only if all fail.
wait_all(@futures)
Done when all have settled, whatever the outcome.
wait_any(@futures)
Done as soon as any has settled.
INTEROP
as_cpan_future
A real CPAN Future that settles when this one does, for code expecting isa('Future').
from_future($cpan_future)
my $f = Fetch::Future->from_future($cpan_future);
A Fetch::Future that mirrors the given CPAN Future.
ASYNC/AWAIT
This class implements the Future::AsyncAwait::Awaitable API, so a request can be awaited directly:
use Future::AsyncAwait;
async sub fetch_title {
my $res = await $ua->get($_[0]);
return $res->content =~ m{<title>(.*?)</title>}s ? $1 : undef;
}
Whatever it awaited, an async sub returns a CPAN Future by default. Naming this class at import makes it return one of these instead:
use Future::AsyncAwait future_class => 'Fetch::Future';
Cancelling the future an async sub returned cancels whichever future it is suspended on.
An async sub takes its loop from the first request it awaits, so one that awaits requests made on two different loops cannot be awaited from outside either. This is the same single-loop rule a chain of then follows. The AWAIT_* methods are the protocol; call the documented names above rather than those.
AUTHOR
LNATION <email@lnation.org>
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION. This is free software, licensed under the Artistic License 2.0.