The main problem is error handling, having to use try / catch is pure cancer and really screw up your closure. You can use catch together with await / async but then you're not dealing with exceptions outside the promises.
The main problem is error handling, having to use try / catch is pure cancer and really screw up your closure. You can use catch together with await / async but then you're not dealing with exceptions outside the promises.
1. do notation works and is used for any monadic type (e.g. lists, parsers, promises, resources like database-connection-contexts, ...) while async/await works for promises only
2. async works on the function-level and only there while do-notation can be used in any place where a normal expression can be used, including being abitrarily nested.
There are more differences, but that should be enough food for the mind to think about it.
You could summarize it as: async/await makes it easier to work with promises on the syntax level and trying to make async code look like sync code, while the do-notation does not try to make async code to look like sync code, but rather embrace that sometimes two different semantical flows are interwined (one inside a monadic context, one pure) and makes it easier to work with them on the syntax level while at the same time making the two look _different_ explicitly.
do-notation doesn't really help to deal with promises, it even makes it harder because it is confusing at the beginning. Async/await makes using promises easier and hides problems for some time at least. I can see why they chose to use async/await.
Just to give an example: error handling with try/catch. That doesn't work with do-notation, but with async/await you can integrate it (more or less at least) and it looks like sync code.