The difference is that, for the duration of the callback, you know the state will only change in ways directly related to the functions you are calling. Between callbacks, anything could happen. But, at least you have an island of sanity within the callback. With coroutines however, any function you call might block for some obscure reason (logging some debug info to a file, for example). That means you can only be sure that the world won't move behind your back as long as you don't call any functions :)
I don't have a lot of experience in this area. I'm just reporting back what I remember hearing.
The difference is that, for the duration of the callback, you know the state will only change in ways directly related to the functions you are calling.
That is true for a single threaded reactor, but in practice I haven't found it to be an especially useful property because naturally that doesn't include external state (i.e. the database).
Getting atomicity right in evented-code has in fact often been a hairier issue for me than doing the same with co-routines or threads, because when you're not allowed to block ever then you quickly find yourself in a situation where you need a retry-mechanism.
Such codebases then tend to quickly converge towards the actor-pattern (tied together by queues) which, ironically, could be had much easier by starting out with co-routines in first place.
It's the same situation when using callbacks.