1. Go to this page and download the library: Download hiblaphp/async library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
hiblaphp / async example snippets
use function Hibla\async;
use function Hibla\await;
use function Hibla\sleep;
// Fetch three resources concurrently. Each async() runs in its own Fiber.
[$user, $orders, $stats] = await(Promise::all([
async(fn() => fetchUser(1)),
async(fn() => fetchOrders(1)),
async(fn() => fetchStats(1)),
]));
// Write sequential async logic that reads like synchronous code
$report = await(async(function () {
$user = await(fetchUser(1));
$orders = await(fetchOrders($user->id));
sleep(0.5); // Suspends this Fiber while other work continues in the background.
return generateReport($user, $orders);
}));
// Outside a Fiber, await() holds the script here while the event loop
// keeps running underneath. Timers fire, and other in-flight work continues.
$user = await(fetchUser(1));
echo $user->name;
use function Hibla\async;
use function Hibla\await;
// A plain function with no special marking and no color
function getUser(int $id): User
{
return await(fetchUser($id));
}
// Works synchronously at the top level without needing async()
$user = getUser(1);
// Works concurrently when wrapped in async() without any changes to getUser()
$promise = async(fn() => getUser(1));
function fetchUserProfile(int $id): PromiseInterface
{
return async(function () use ($id) {
$user = await(Http::get("/users/$id"));
$avatar = await(Http::get("/avatars/$id"));
return ['user' => $user, 'avatar' => $avatar];
});
}
async(function () {
// Multiple profiles load concurrently because each async() call
// runs in its own Fiber and suspends independently at each await()
[$page1, $page2, $page3] = await(Promise::all([
fetchUserProfile(1),
fetchUserProfile(2),
fetchUserProfile(3),
]));
});
use function Hibla\async;
$promise = async(function () {
return 'hello from a fiber';
});
$promise->then(fn($value) => print($value)); // hello from a fiber
$start = microtime(true);
async(function () {
await(delay(1));
echo "Task 1 done\n";
});
async(function () {
await(delay(1));
echo "Task 2 done\n";
});
async(function () {
await(delay(1));
echo "Task 3 done\n";
});
// All three run concurrently. The total time is ~1 second, not 3.
echo microtime(true) - $start; // ~1.0
// Wrong: blocks the entire loop for 2 seconds
async(function () {
\sleep(2); // PHP's native sleep function stalls everything
echo "done\n";
});
// Correct: suspends this Fiber cooperatively so the loop stays free
async(function () {
sleep(2); // Hibla's sleep function. Use function Hibla\sleep
echo "done\n";
});
$promise = async(function () {
throw new \RuntimeException('Something went wrong');
});
$promise->catch(fn($e) => print($e->getMessage())); // Something went wrong
// Wrong: allocates a full Fiber just to await one existing promise
$result = await(async(fn() => await(Http::get('/api/data'))));
// Correct: await the promise directly without needing a Fiber
$result = await(Http::get('/api/data'));
function getUserName(int $id): string
{
$user = await(fetchUser($id));
return $user->name;
}
// Wrong: getUserName() already works in both contexts
$name = await(async(fn() => getUserName(1)));
// Correct: call it directly
$name = getUserName(1);
// Only wrap in async() when you specifically want concurrent execution
$promise = async(fn() => getUserName(1)); // justified due to explicit concurrency
// Good use: multiple awaits with logic between them
$promise = async(function () {
$user = await(fetchUser(1));
$orders = await(fetchOrders($user->id));
$ratings = await(fetchRatings($user->id));
return processData($user, $orders, $ratings);
});
use function Hibla\await;
$user = await(fetchUser(1));
echo $user->name;
// Outside a Fiber: holds the script here while the event loop keeps running underneath
$user = await(fetchUser(1));
// Inside a Fiber: suspends cooperatively
async(function () {
$user = await(fetchUser(1)); // other work runs while waiting
echo $user->name;
});
use Hibla\Cancellation\CancellationTokenSource;
use function Hibla\async;
use function Hibla\await;
$cts = new CancellationTokenSource(5.0); // 5 second timeout
async(function () use ($cts) {
try {
$user = await(fetchUser(1), $cts->token);
$orders = await(fetchOrders($user->id), $cts->token);
return compact('user', 'orders');
} catch (\Hibla\Promise\Exceptions\CancelledException $e) {
echo "Operation timed out or was cancelled\n";
}
});
// Plain functions using await() internally n await(Http::get("/users/$id")->then(
fn($r) => User::fromArray(json_decode($r->getBody(), true))
));
}
function getUserWithOrders(int $id): array
{
$user = getUser($id);
$orders = await(fetchOrders($user->id));
return compact('user', 'orders');
}
// 1. Synchronous: holds the script at each call while the event loop keeps running underneath
$data = getUserWithOrders(1);
// 2. Single async task: runs in a Fiber and suspends cooperatively
$promise = async(fn() => getUserWithOrders(1));
// 3. Concurrent: multiple users fetched concurrently
$promises = array_map(
fn($id) => async(fn() => getUserWithOrders($id)),
[1, 2, 3, 4, 5]
);
await(Promise::all($promises));
// 4. With concurrency limiting
await(Promise::concurrent(
array_map(
fn($id) => fn() => async(fn() => getUserWithOrders($id)),
range(1, 100)
),
concurrency: 10
));
use function Hibla\asyncFn;
function processRecord(array $record): array
{
$enriched = await(enrichRecord($record));
$validated = await(validateRecord($enriched));
return $validated;
}
// Create an async version without changing processRecord()
$asyncProcess = asyncFn('processRecord');
// Primary use case: passing to Promise::map() or Promise::concurrent()
await(Promise::map($records, $asyncProcess, concurrency: 10));
> use function Hibla\sleep; // sleep(1); // Hibla's sleep — correct
> \sleep(1); // PHP's native sleep — stalls the entire loop
> });
>
use function Hibla\inFiber;
function getStatus(): string
{
if (inFiber()) {
return await(fetchStatusAsync());
}
return fetchStatusSync();
}
use Hibla\Async\AsyncEnvironment;
// Activating strict validation (Highly recommended for high-concurrency daemons)
AsyncEnvironment::enableStrictAwait();
// Restoring the cooperative blocking fallback (The default setting)
AsyncEnvironment::disableStrictAwait();
use Hibla\Cancellation\CancellationTokenSource;
use function Hibla\async;
use function Hibla\await;
$cts = new CancellationTokenSource();
$workflow = async(function () use ($cts) {
$connection = openConnection();
try {
$user = await(fetchUser(1), $cts->token);
$orders = await(fetchOrders($user->id), $cts->token);
$report = await(generateReport($user, $orders), $cts->token);
return $report;
} catch (\Hibla\Promise\Exceptions\CancelledException $e) {
echo "Workflow cancelled\n";
return null;
} finally {
// Always runs on normal completion, exception, or cancellation
$connection->close();
}
});
// Cancel from anywhere, causing the next await() in the workflow to throw
Loop::addTimer(2.0, fn() => $cts->cancel());
$result = await($workflow);
$cts = new CancellationTokenSource(5.0);
$workflow = async(function () use ($cts) {
// Http::get() has an onCancel() handler that aborts the curl request.
// Passing $cts->token to await() is enough, so no manual track() call is needed.
$response = await(Http::get('https://api.example.com/users'), $cts->token);
$data = await(Http::get('https://api.example.com/orders'), $cts->token);
return compact('response', 'data');
});