Japronto does not seem to be under active development any more, but async programming is definitely the way to go in order to squeeze the most performance out of the hardware at ones disposal.
I put down some thought round this that tracks my own journey to understanding the concept (sorry if this is too basic for you, take it or leave it, and please note that I'm not an expert by a long shot).
It's not guaranteed that you have the same way of picturing things, but here goes: programs normally run in one direction, executing one line at the time from top to bottom (vertically). But one or more of those 'vertical' commands may send the computer off in a horizontal direction too (async calls), that have a 'horizontal' chain of commands.
The problem that I (and I think many with me) have had a hard time grokking at first is that the 'vertical' flows continue immediately after having issued a 'horizontal'(async) call. The computer doesn't wait for the async call to come back. To do something after the async call has finished you have to tack a new call onto the result of the async call in the 'horizontal' chain of events, previously often leading to what was called 'callback hell' in Nodejs programming.
Not sure about PHP but one may get round the problem of callback hell in the JavaScript world by using async/await and promises which mimics synchronous programming, i.e. program flow in the 'vertical' direction is actually halted until the async calls return a result. Personally I find that this adds another level of abstraction that sometimes may make things even more difficult to understand and debug. I prefer wrapping async calls in some queue construct instead (which takes care of the chaining of consecutive async calls), works for me.
In short, synchronous commands are automatically 'chained' top to bottom in code, asynchronous commands have to be chained manually after the completion of each async bloc of code. I believe multi-threaded process programming is just a more advanced case of async calls that often need to be 'orchestrated', i.e. coordinated in a way that simple async calls usually don't need. But all types of async programming comes with some special issues, of which race-conditions is maybe the most common, i.e. when several async processes are trying to change the value of a shared asset in an ad-hoc manner.