Eventually it'll happen; you'll be writing a library that's responsible for making a bunch of network calls, and because you've worked in IO-heavy applications before, you've already been sold on asynchronous programming patterns and because you've hated having to turn away so many modules on CPAN that do the exact job you want because they completely ignore the needs of the asynchronous crowd, you're going to write your library (or a version of the library) so that it can integrate easily with an event-loop framework by providing an asynchronous API.
One of the biggest rookie mistakes I made in the beginning, was writing functions that return AnyEvent::CondVar objects. It can work just fine if your entire application uses and expects other condition variables and you only need a small handful of them, but when the application grows and you perhaps start integrating with libraries whose functions return Promises or Futures, condition variables only get in the way. And when you start calling many functions that all return condition variables, you wind up in an ugly spaghetti of callbacks.
Return promises or futures and, in your application code, utilise the chaining/sequencing/pipelining features so it doesn't look like spaghetti. You'll end up with cleaner-looking code that's more easily maintainable, reads like synchronous code, and is easier for other developers to dive into.