4

我正在尝试使用 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().


}); 
4

2 回答 2

5

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

可以使用特定于您的任务的模块来执行异步代码。如果您尝试发出 HTTP 请求,可以使用ReactPHPhttp-client模块。如果要异步执行系统命令,可以考虑使用子进程模块。

如果你想做一些完全不同或定制的事情,你应该将工作抽象成它自己的异步行为,类似于Predis 异步库。也许使用 promise 模块来提供成功/失败回调。

于 2016-01-03T02:47:54.543 回答
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.


});

我想你有一个 global $loop = React\EventLoop\Factory::create();,大多数时候它是有意义的。

这里$loop->addTimer()调用 return 立即,所以iterate()返回了未解决的承诺,所以该方法then()被立即调用,并且顺序执行继续你的echo end at ...

then()方法将行为附加到返回的承诺,不执行作为参数传递的函数。但是首先要返回promise,问题是sleep不是异步睡眠,而是真的睡了2秒!

请注意,您拥有的 javascript 中没有 sleep 对应项setTimeout(),其行为就像这样$loop->addTimer()

于 2018-11-25T07:07:05.047 回答