I've been working to teach Promise thinking to another developer. Promises (and callbacks) are "easy" from a functional programming background, but for someone without much of a functional programming background like my colleague, it's certainly confusing. There is a rigor needed in writing Promises (and callbacks) in knowing what is in each closure and making sure that the return values of individual callbacks are in the "right shape" for the next callback in the chain.
Loops with Promises involve confusing things like higher level combinators like Promise.all and Promise.race, and that requires more new sorts of reasoning about return types than a "traditional" `for (let thing of list) { let result = await doThe(thing); /* do something with result */ }` loop.
Not that a need for things like Promise.all and Promise.race goes away with async/await but that it moves from being a must need to learn on the first pass of writing an algorithm out to being a performance optimization in advanced scenarios that can be done easier by someone more senior and/or in a later pass of code writing (such as a code or performance review).
It makes the learning curve to "doing asynchronous code right" a lot less sharp, smoothing out some of the complexity, and that can be a huge win for any team with a mixture of developers of different skill levels and skill sets.
I personally prefer the functional approach with bound methods to avoid callback hell, improve readability and ensure there is minimal amount of memory leaking.
That being said, async/await makes callback programming easier so it is another tool which may come handy in the situations where you really need it.
Think of async as return and await as bind.
I hear the words you are saying, I just cant visualise the concept. Could you ELI5, or post an example?