You are correct in that nodejs is running in a single thread. You can start separate processes and put a load balancer in front of those processes to make use of multicore processors, but that is not implemented in the node itself.
However, node does not spin up a thread for every async function it encounters. It puts those function calls into event loop that runs constantly. The important thing here is that event loop is non-blocking, which means the order of function call excecution is not guaranteed - this is the reason why callbacks are the basis for all node.js programs. That means that for example while one function is waiting for file to be found in the filesystem and read to the buffer, event loop does not stop everything to wait for it to complete and continues to the next call. But in no way is this multi-threaded behaviour. Event loop is not excecuting anything in parallel, it's just constantly switching between tasks. This is just multitasking :)
In your example, a while(true) is blocking the event loop, because it's not an async function call. Do not forget that not everything in javascript is async - only function calls can be async and not other language constructs, such as loops or conditionals. So in your example you run async file reader which is added to the event loop and started. While the file system is doing it's thing, event loop has nothing to do and moves on to console.log("before loop") message. After that you block event loop with while(true) loop. This means event loop cannot put it on hold and go to the filereader anymore.
Hope that clears things up. The main takeaway here is that not everything in javascript is or has to be asynchronous, but most time-consuming operations that are dealing with different devices, such as filesystem or network, are implemented in a non-blocking way. Async function only makes sense when it uses some outside component - you would not use async square root function, as it would block the event loop just the same. This is the reason why node.js is not recommended for heavy computational operations, such as audio/video encoding - async advantage just would not make sense here.