Basically, async I/O gives you more options than "block the whole world while you go read this stuff", and that means that old idioms aren't effective.
You gain more control: can choose when to block, when to limit concurrency and when to just launch a bunch of tasks at the same time. At the same time, you need to adopt a few new patterns, since you can't/don't feel right blocking execution every time you use an external data source. It's definitely a tradeoff and not a magic bullet.
You don't get to choose when to block. Blocking becomes an error which hangs the event loop. The only option for blocking calls is to use a thread pool that sends events back to the event loop when a thread finishes running.
You're right, I should've said "emulate blocking by checking that all of the tasks we queued have completed upon finishing a task before proceeding while allowing the event loop to run" instead of "blocking". It's not really blocking the event loop, only a controlling the flow of a particular path of execution. Only a few native API's provide synchronous versions that will block the entire process until they complete - like the filesystem API's fs.readFileSync.