It's obsolete now, but before async/await was part of JS proper I worked on a compile-to-JS language that handled this by compiling to callbacks: https://github.com/rzimmerman/kal
It included try/catch support and fancy stuff, like loops. The source may be interesting for anyone interested in compilers: https://github.com/rzimmerman/kal/blob/master/source/generat...
The Kal compiler is written in Kal, but it's supposed to be easy to read. Surprisingly the browser demo still works: http://rzimmerman.github.io/kal/demo.html