Generally speaking, when you are doing I/O-intensive work with little to no CPU-overhead, non-blocking or async is best. When the operations are, however, CPU-intensive, a threaded model tends to make more sense.
The reason for this is simple: It's usually a bad idea to block the event loop for longer periods of time - as would happen when using an asynchronous model for CPU-heavy computations.
When you start blocking the event loop, things like timers don't behave like they should, since they can only trigger once you return control to the event loop. This is usually not what you want.