That's the problem in a nutshell, It needn't be that way.
Blocking IO is just one aspect. Anything that is not instantaneous is blocking. Without the ability to preempt something taking a long time you will always be prone to the user interface freezing.
Methods like Array.map() are specifically designed to manage bulk operations immediately, which, without preemption, is at odds with a design where the user interface should perform with the lowest latency.