Using event listeners was one way to watch out for async operations, but there are times the listeners will trigger too early and the event will happen incorrectly. That's where promises come in.
The problem that promises solve is the issue of executing code at the right time after another operation has completed. For example, when you see the loading wheel on a website a bunch of things are happening in the background. There are probably some database calls going on or some calculations being run to determine which content to show on the page.
When all of that background stuff finishes, you'll either see the screen you were waiting for or an error. That's where promises come in. A promise will wait for all of that background stuff to finish with their individual timings and then it will execute the appropriate code.
So after all of the operations have finished, the promise will return a result of either success or failed. Depending on how you want your code to work, you can set up callback functions to handle the success or fail cases. That way you can be sure of what will happen on the screen for a user regardless of what happens on the back-end.
This literally means you can slap the then() method at the end of a promise and run completely new async processes using the results. You can chain as many of them together as you need and they will all run the code asynchronously.
Here's a picture of what promises look like:
As you can see in this example, the promise won't do anything until all of the tasks it's waiting for are done. Then it executes a callback that uses the results of those tasks. Then you can use then() to continue the process using some other tasks.
Hey! You should follow me on Twitter because reasons: https://twitter.com/FlippedCoding