In JavaScript, events are blocked by currently executing code. Callbacks allow asynchronous code to be executed after the current execution thread is clear. Promises provide a standard way to manage asynchronous processes by sharing a communication object between the consumer and producer of asynchronous results. This avoids nested callbacks and makes error handling and composition easier.