amonite / async
PHP async, await and Promise classes, about to run async methods
Installs: 3
Dependents: 0
Suggesters: 0
Security: 0
Stars: 3
Watchers: 2
Forks: 0
Open Issues: 0
pkg:composer/amonite/async
Requires
- php: >=7.2
This package is not auto-updated.
Last update: 2026-01-07 22:29:37 UTC
README
Asynchronous paradigm for PHP!
It's now available! Just start your asynchronous environment with await function, then do whatever you want with functions and classes below!
Installation
You can :
- run
composer require amonite/async, or - copy
async.pharfile in your project directory and load it with arequire.
Context
As a JavaScript developer, I like the asynchronous paradigm. I decided to export this paradigm to allow PHP to take advantage of it: now, produce libraries that can process information while waiting for them to load data.
Non-blocking events
In PHP, by default many functions stop script until the end. That's helpful with common arithmetic functions, but you wan also observe it when you request a data from your database (no matter your software), when you load a file from your computer or internet, when you use some socket, or run a command-line.
When your script wait for an other software, then your process is down. When a client start a request to the server, he waits for the previous client end of script. When thousands clients wait for a single client who waits for an only one heavy SQL request with 30+ seconds duration, then the server could crash as if it was a DDOS attack.
By using this library, I will develop a non-blocking HTTP server, then HTTPS, HTTP/2, SQL and filesystem reader/writer. Hope it will help!
Usage
Understand await/async environment
Function await create an environment that allows to register an async event. An asynchronous event is an non-blocking function that continue script until end of a writing file function, a reading file function, connection start function and so on.
Creating await environment
The function $fn_env in await($fn_env) : mixed create an asynchronous environment, and wait (many ticks) for all asynchronous events ends. The script is blocked in this function until the end of its async functions. If $fn_env returns a Promise, the await function returns its anwser resolved or throw its error rejected.
File wrapper test/wrap.php :
<?php require_once "async.phar"; //require_once "index.php"; await(function () { require "await.php"; require "async.php"; });
Triggering asynchronous events
The function $test in async($test, $then) : null is executed each tick of await function until it returns a truthfully value (or throws an error).
Here the file wrap let all required files to use async functions.
In the next file, I combined both async and await. First async is registered, then we wait for await end of function and async events, and then register the last async function.
File test/await.php :
<?php $date = microtime(true); async(function () use ($date) { if($date + 4 < microtime(true)) return true; }, function ($err) { if ($err) echo "err:$err\n"; echo "first resolved\n"; }); echo "first entered\n"; await(function () use ($date) { async(function () use ($date) { if($date + 3 < microtime(true)) return true; }, function ($err) { if ($err) echo "err:$err\n"; echo "second resolved\n"; }); echo "second entered\n"; async(function () use ($date) { if($date + 2 < microtime(true)) return true; }, function ($err) { if ($err) echo "err:$err\n"; echo "third resolved\n"; }); echo "third entered\n"; }); async(function () use ($date) { if($date + 1 < microtime(true)) return true; }, function ($err) { if ($err) echo "err:$err\n"; echo "fourth resolved\n"; }); echo "fourth entered\n";
The console will print:
(t+0s) > first entered
(t+0s) > second entered
(t+0s) > third entered
(t+2s) > third resolved
(t+3s) > second resolved
(t+3s) > fourth entered
(t+3s) > fourth resolved
(t+4s) > first resolved
Use Promise class
A Promise is commonly used to flat asynchronous and verbose functions. It follows JavaScript standard.
File test/promise.php :
<?php require_once __DIR__ . "/../index.php"; $date = microtime(true); $p = new Async\Promise(function ($resolve, $reject) use ($date) { while (microtime(true) < $date + 2) time_nanosleep(0,1); $resolve(); }); $p->then(function () { echo "I waited for 2 seconds.\n"; throw new Error("test error"); }); $p->catch(function () { echo "An error occurred in the promise or in then() function.\n"; }); var_dump(await(function () use ($date) { return Async\Promise::all(array( Async\Promise::resolve(3.14), Async\Promise::async(function () { return "Fibonacci"; }), Async\Promise::async(function () use ($date) { if (microtime(true) > $date + 3) return "Time elapsed!"; }) )); }));
(!) In this example, the code is blocked until the 2 seconds passed, then wait for every Promise to be resolved.
Use Async class
If you want to full manage your async events, you may prefer use the class Async.
File test/async.php :
<?php $delay = microtime(true) + 3; $test = function () use ($delay) { if ($delay < microtime(true)) return "delay"; }; $then = function ($err, $m) { if ($err) { echo "$err err"; } else { echo "$m then\n"; } }; new Async\Async($test, $then);
The return in a blocking context
Now you've been played with asynchronous items, you can return in a synchronous script, with its blocking function and its wasting of time. Lucky you! You can get await value by returning a Promise in its environment. Function await is able to get result of a Promise returned. Warning: if your Promise reject, then await will throw the error!
File test/await_async.php:
<?php require_once "index.php"; $res = await(function () { // do async stuff // ... return new Async\Promise(function (\Closure $resolve, \Closure $reject) { $d = 3; $t = microtime(true) + $d; async(function () use ($t){ return microtime(true) > $t; }, function ($err) use ($resolve, $reject, $d) { if ($err) $reject($err); else $resolve("Now $d seconds elapsed. Well done!\n"); }); }); }); echo $res;
Documentation
Function await
Create an async instance and register it in await context.
- Syntax:
await (\Closure $env) : mixed - Parameter:
$env {Closure.<$self {Closure}>}is a function executed to register every async instances. - Returns:
{*|null}if$envreturns a Promise resolved, return its result. - Throws:
{Throwable}if$envthrows or returns a Promise rejected (return its error).
Function async
Register a function that wait to be resolved or rejected each ticks of await environment or a timeout error (3000ms if not unset).
- Syntax:
async (\Closure $test, \Closure $then = null) : null - Parameters:
$fn {Closure.<>}is a first function executed each ofawaitenvironment until it returns a truthfully value, sent in$thenas second parameter; if function throws an error, send it to$thenas first parameter.$then {Closure.<$error {Throwable|null}, $result {*}>}is the function executed right after an event happened in$fn; when$fnresolves, the result is sent as second parameter$resultor when$fnthrows error, the error is sent as first parameter$error(else$errorisnull).
- Returns:
null. - Throws:
{Async\AsyncError}if this instance is not created in anawaitcontext.
Class Async\Await
Method __construct
Create an async instance and register it in await context.
- Syntax:
$await = new Async\Await (\Closure $env) : {Async\Await} - Parameter:
$env {Closure.<$self {Closure}>}is a function executed to register every async instances. - Returns:
{Async\Await}new instance. - Throws:
{Throwable}if$envthrows.
Method env
Run function in await context, and add async instances found in $env.
- Syntax:
$await->env (\Closure $env) : mixed - Parameter:
$env {Closure.<$self {Closure}>}is a function executed to register every async instances. - Returns:
{*|null}if$envreturns a Promise resolved, return its result. - Throws:
{Throwable}if$envthrows or returns a Promise rejected (return its error).
Static isAwaitContext
Tell if your script is currently in an await context.
- Syntax:
Async\Await::isAwaitContext() : boolean - Returns:
{boolean}trueif script is in an await context.
Static add
Static remove
Class Async\Async
Method __construct
Register a function that wait to be resolved or rejected each ticks of await environment or a timeout error (3000ms if not unset).
- Syntax:
$async = new Async\Async (\Closure $test, \Closure $then = null) : Async\Async - Parameters:
$test {Closure.<>}is a first function executed each ofawaitenvironment until it returns a truthfully value, sent in$thenas second parameter; if function throws an error, send it to$thenas first parameter.$then {Closure.<$error {Throwable|null}, $result {*}>}is the function executed right after an event happened in$test; when$testresolves, the result is sent as second parameter$resultor when$testthrows error, the error is sent as first parameter$error(else$errorisnull).
- Returns:
{Async\Async}new instance. - Throws:
{Async\AsyncError}if this instance is not created in anawaitcontext.
Method test
Verify that the $test function returns a truthfully answer: if it is truthfully, execute $then function; else do nothing; or catch error and send it to $then function.
- Syntax:
$async->test() - Returns:
{Async\Async}this instance.
Class Async\Promise
Method __construct
Create a Promise instance. Promise helps to flat async functions in a single instance.
- Syntax:
$prom = new Async\Promise(\Closure $fn) : Async\Promise - Parameter:
$fn {Closure.<$resolve {Closure.<$result {*}>}, $reject {Closure.<$error {Throwable}>}>}is the function executed that wait for$resolveexecution or$rejectexecution or an error thrown. - Returns:
{Async\Promise.<$result {*}>.<$error {Throwable}>}new instance.
Method then
Register a function to execute when Promise resolves.
- Syntax:
$prom->then(\Closure $fn) - Parameter:
$fn {Closure.<$result {*}>}is the function executed when Promise is resolved. The$resultvalue is sent in$resolve. - Returns:
{Async\Promise}self instance.
Method catch
Register a function to execute when Promise rejects.
- Syntax:
$prom->then(\Closure $fn) - Parameter:
$fn {Closure.<$error {Throwable}>}is the function executed when Promise is rejected. The$errorvalue is sent in$reject. - Returns:
{Async\Promise}self instance.
Method finally
Register a function to execute after Promise resolves or rejects.
- Syntax:
$prom->then(\Closure $fn) - Parameter:
$fn {Closure.<$result {*}>}is the function executed after Promise is resolved or rejected. The$resultvalue is sent in$resolveor in$reject. - Returns:
{Async\Promise}self instance.
Static resolve
Helpful function for creating an already resolved Promise.
- Syntax:
Async\Promise::resolve($result {*}) - Parameter:
$result {*}is the value resolved - Returns:
{Async\Promise}new instance.
Static reject
Helpful function for creating an already rejected Promise.
- Syntax:
Async\Promise::resolve($error {*}) - Parameter:
$error {Throwable}is the value rejected - Returns:
{Async\Promise}new instance.
Static all
Helpful function for creating a Promise that wait for list $list of Promise to be resolved.
- Syntax:
Async\Promise::all($list) - Parameter:
$list {Array.<{Async\Promise} ...>}a list of Promises that should be resolved. - Returns:
{Array.<{*} ...>}the answer of each Promises.
Static any
Helpful function for creating a Promise that wait for one Promise of list $list of Promise to be resolved.
- Syntax:
Async\Promise::any($list) - Parameter:
$list {Array.<{Async\Promise} ...>}a list of Promises that could be resolved. - Returns:
{*}the answer of the first resolved Promise.