reactPHP 承诺同步执行

reactPHP promises executed synchoniously

我正在尝试使用 reactPHP 实现类似 js 的承诺。 但是由于某些原因,同步执行的方法,end_at 仅在 promise 被解析后打印。

代码:

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().


}); 

承诺本身不是异步的。承诺本身只是让您能够 运行 一些代码,然后根据成功或失败进行不同的回调,然后将这些概念中的几个链接在一起。

可以使用特定于您的任务的模块来执行异步代码。如果您尝试发出 HTTP 请求,则可以使用 ReactPHP's http-client module. If you want to execute a system command asynchronously, you might consider using the child-process 模块。

如果您希望做一些完全不同或定制的事情,您应该将工作抽象为它自己的异步行为,类似于 Predis async library。也许使用 promise 模块来提供 success/failure 回调。

您的代码中的问题是您使用了阻塞函数:sleep()

这里引用了一些阻塞调用: https://github.com/reactphp/react/wiki/FAQ

但 promise 本身是异步的:它提供了在函数被调用之前声明要在链中调用的函数的能力。

实际上通过调用一个函数你必须等到函数被执行,但是声明"then you must run this",你并不是真的运行它,只要第一次调用returned.

所以

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() 立即调用 return,所以 iterate() returnpromise,未解决,所以立即调用方法 then(),并且顺序执行继续你的 echo end at ...

then() 方法将行为附加到 returned 承诺,不执行作为参数传递的函数。但首先promise必须returned,问题是sleep不是async sleep,而是真的睡了2秒!

请注意,您在 javascript 中没有睡眠对应物,您有 setTimeout(),它的行为就像这样 $loop->addTimer()