0

I have the following test php code:

use React\EventLoop\Loop;
$loop = Loop::get();
$reason = "unknown";

\Ratchet\Client\connect('wss://demo.piesocket.com/v3/channel_1?api_key=VCXCEuvhGcBDP7XhiJJUDvR1e1D3eiVjgZ9VRiaV&notify_self', [], [], $loop)->then(function($conn) use ($loop, &$reason){
    $conn->on('message', function($msg) use ($loop, $conn, &$reason){
        echo $msg."\n";
        if ($msg == "quit") {
            $conn->close();
            $loop->stop();
            $reason = "quit";
        }
    });
}, function ($e) {
    echo "Could not connect: {$e->getMessage()}\n";
});

echo "the echo $reason\n";

The code mostly works, it connects to the websocket and prints messages on the command line that are sent through the websocket. Also when I send quit it stops the connection and the script ends.

However the last echo in the script, the "the echo $reason" echo, is printed first thing the script starts. I would like to somehow wait for the websocket to finish and then run the echo statement. How do I do this?

In the end the websocket code is going to be a small subroutine of a bigger script. I want the bigger script to wait for the subroutine to finish.

Veda
  • 2,025
  • 1
  • 18
  • 34
  • Simple: put `echo "the echo $reason\n";` inside the `if ($msg == "quit") {`...just like all the other code you're expecting to run when the "quit" command is issued and have already placed there. Maybe I missed something but I'm not sure why that's a puzzle? – ADyson May 10 '22 at 13:23
  • `I want the bigger script to wait for the subroutine to finish.`...again its simple: anything which should occur after the "quit" command is issued must be within - or within a function called from - the `if` block I mentioned above. There's no other way for PHP to know that this event has occurred. Since it's all asynchronous (or at least pseudo-asynchronous), you cannot expect the other code to wait for the event. Instead, rethink the approach, and design it so subsequent tasks are triggered when the event occurs, rather then trying to "wait" for an event from an outer code block. – ADyson May 10 '22 at 13:26
  • [How to return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) is talking primarily about JavaScript, but the principles and logic talked about are equally applicable here. – ADyson May 10 '22 at 13:27

1 Answers1

0

Add

$loop->run();

before the echo, the run() will block the thread until it has finished. So the echo will be printed at the end of the script and the $reason will be filled in as expected.

The Loop::get() function has this comment:

Automatically run loop at end of program, unless already started or stopped explicitly.

So if you did not start it manually, it will start it at the end of the script. In my opinion a weird feature, but running it manually bypasses it.

Veda
  • 2,025
  • 1
  • 18
  • 34