doAsync1(function () { doAsync2(function () { doAsync3(function () { doAsync4(function () { }) }) }) Callback hell is subjective, as heavily nested code can be perfectly fine sometimes. Asynchronous code is hellish when it becomes overly complex to manage the flow. A good question to see how much “hell” you are in is: how much refactoring pain would I endure if doAsync2 happened before doAsync1? T