For this specific case, just use traditional blocking functions:
val another_path = readFileSync(path);
val data = readFileSync(another_path);
console.log(data.length);
The "runtime" (for instance the OS, or a task system) will take care of scheduling other things that are ready to run while the blocking functions are "stuck". That's exactly what processes and threads had been invented for.
This particular one, yes. However, most programs are a bit more complicated than that. That and Async is mostly used for io operations. In which case, the value here is not from non-blocking operations but from freeing up the CPU while this operation finishes execution. You can think of that as another form of executing this program on a separate thread (since the CPU will be freed to do other tasks).
Exactly like that, but using blocking functions. Then I run the code in a worker pool or in a greenlet runtime. The kernel and runtime take care of putting threads to sleep when they hit blocking IO.