The problem in your code is that you are using a blocking function: sleep()
Here are cited some blocking calls:
https://github.com/reactphp/react/wiki/FAQ
But promise by itself is asynchronous: it gives the abilities to declare the function to be called in the chain before those are been called.
In fact by calling a function you must wait until the function is executed, but declaring that "then you must run this", you are not really running it, as soon as the first call returned.
So
function iterate() {
global $loop;
$deferred = new \React\Promise\Deferred();
$loop->addTimer(2, function () use ($deferred) {
$deferred->resolve();
});
return $deferred->promise();
}
Route::get('test/async', function() {
echo "start execution at ".time()."<br>"; // this executed first
iterate()->then(function($result) {
echo "got result result at ". time() . "<br>"; // this when solved
}, function($error) {
}, function ($finally) {
});
echo "end at " . time(); // this is executed only after iterate() and then() returns.
});
I supposed you have a global $loop = React\EventLoop\Factory::create();
, most of the time it make sense.
Here $loop->addTimer()
call return immediately, so iterate()
returns the promise, unsolved, so the method then()
is called immediately, and the sequencial execution goes on with your echo end at ...
then()
method attach a behaviour to the returned promise, does not execute the function passed as argument. But first the promise must be returned, the problem is that sleep is not an async sleep, but it really sleeps for 2 seconds!
Note that you do not have a sleep counterpart in javascript you have setTimeout()
, that behaves just like this $loop->addTimer()