Callback Hell!

Here is the structure of our application, which simulates getting transactions for the most recent loan associated with the account number of our user.

// getUser(), getLoans(), and getTransactions() not shown! console.log("listening for events"); getUser(1, (user) => { getLoans(user["Account number"], (loans) => { getTransactions(loans["Most recent"], (transactions) => { console.log(transactions); }); }); }); console.log("still listening for events!");

Notice, if the functions getUser, getLoans, and getTransactions were synchronous, the program would look like this:

// getUser(), getLoans(), and getTransactions() not shown! console.log("listening for events"); const user = getUser(1); const loans = getLoans(user["Account number"]); const transactions = getTransactions(loans["Most recent"]); console.log(transactions); console.log("still listening for events!");

The second snippet corresponding to synchronous code is arguably more readable and easier to understand.

In the asynchronous version, because of the callbacks, we have a deeply nested structure. In practice, this can get much deeper. This pattern is referred to as the callback hell (some resources call it "Christmas tree problem").

method1(arg1, (arg2) => { method2(arg2, (arg3) => { method3(arg3, (arg4) => { method4(arg4, (arg5) => { method5(arg5, (arg6) => { method6(arg6, (arg7) => { // ... // CALLBACK HELL // ... }); }); }); }); }); });