我试图用reactPHP实现类似js的承诺。
但由于某些原因,方法同步执行,end_at
仅在承诺解决后打印。
代码:
function iterate() {
$deferred = new \React\Promise\Deferred();
sleep(2);
$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 is second
}, function($error) {
}, function ($finally) {
});
echo "end at " . time(); // this is executed only after then().
});
答案 0 :(得分:1)
承诺本身不是异步的。一个承诺本身只是让你能够运行一些代码然后基于成功或失败的不同回调,然后将这些概念链接在一起。
可以使用特定于您的任务的模块来执行异步代码。如果您尝试发出HTTP请求,可以使用ReactPHP的http-client模块。如果要异步执行系统命令,可以考虑使用child-process模块。
如果您想要做一些完全不同或定制的事情,您应该将工作抽象为自己的异步行为,类似于Predis async library。也许使用promise模块提供成功/失败回调。
答案 1 :(得分:0)
代码中的问题是您正在使用阻止功能:sleep()
在此引用了一些阻止调用: https://github.com/reactphp/react/wiki/FAQ
但是promise本身是异步的:它具有在被调用之前在链中声明要调用的函数的能力。
实际上,通过调用一个函数,您必须等到该函数执行后才能使用,但是声明“然后必须运行此函数”,则实际上并没有在第一次调用返回时立即运行它。
所以
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.
});
大多数情况下,我认为您有一个全局$loop = React\EventLoop\Factory::create();
。
这里$loop->addTimer()
调用立即返回,因此iterate()
返回未解决的承诺,因此方法then()
立即被调用,并且顺序执行继续执行您的echo end at ...
then()
方法将行为附加到返回的Promise,不执行作为参数传递的函数。但是首先必须兑现诺言,问题是睡眠不是异步睡眠,但实际上会睡2秒钟!
请注意,您在JavaScript中没有{@ 1}}的睡眠对象,其行为类似于setTimeout()