Await is nice, but even with promises, I'd settle with people using them correcly: return something in the promise to the next one can use it without nesting.
Thus you don't need to make things like 'one' and 'two' into scoped variables that require nesting the second function into the first one so it can see them, and you can split those functions out of being inline lambdas.
Or early Promise libs like coolaj86's futures which included a sequence, letting you do the same sort of thing:
while also being able to make nice little future() objects you could return from functions and pass around. To be fair it's still JS and lots of third party code needed regular old callbacks so it was still easy to get excessive levels of nesting of various things that leave you with function-closing sequences like });}});return future;} or });}}).end(buf);} that could make a Lisper blush.
These days it's quite a bit nicer having native Promises, a better community-wide understanding of how to use them, but also the syntactic sugar of async/await improves over the waterfall/sequence/.then&.catch chaining styles (especially when it comes to modifications where you want to use data from previous stages of the chain in later stages).
The ResultAsync class in neverthrow has chaining as well as splitting on ok/error - I find this really nice because you can also do away with exceptions at the same time.
I feel like fp-ts is even more powerful for this - provided you (and your entire team / every new hire) can navigate the steep learning curve which tbh defeated me when I tried to learn it in a couple of days last week
I'd argue (from memory!) that there are solid edge cases for nesting promises .. probably all scope-related, where multiple async operations are required for a result that would otherwise require scope-leak / pollution.
Or early Promise libs like coolaj86's futures which included a sequence, letting you do the same sort of thing:
while also being able to make nice little future() objects you could return from functions and pass around. To be fair it's still JS and lots of third party code needed regular old callbacks so it was still easy to get excessive levels of nesting of various things that leave you with function-closing sequences like });}});return future;} or });}}).end(buf);} that could make a Lisper blush.These days it's quite a bit nicer having native Promises, a better community-wide understanding of how to use them, but also the syntactic sugar of async/await improves over the waterfall/sequence/.then&.catch chaining styles (especially when it comes to modifications where you want to use data from previous stages of the chain in later stages).