3

When reading about async and await, I noticed that it's almost an equivalent of generator functions. Consider this fragment from TypeScript Deep Dive:

Async Await

(...)

// Not actual code. A thought experiment
async function foo() {
    try {
        var val = await getMeAPromise();
        console.log(val);
    }
    catch(err) {
        console.log('Error: ', err.message);
    }
}

(...)

Generated JavaScript

You don't have to understand this, but it's fairly simple if you've read up on generators. The function foo can be simply wrapped up as follows:

const foo = wrapToReturnPromise(function* () {
    try {
        var val = yield getMeAPromise();
        console.log(val);
    }
    catch(err) {
        console.log('Error: ', err.message);
    }
});

where the wrapToReturnPromise just executes the generator function to get the generator and then use generator.next(), if the value is a promise it would then+catch the promise and depending upon the result call genertor.next(result) or genertor.throw(error). That's it!

What is the reason that it ended up being "a new feature"? IMHO just using that wrapToReturnPromise function from some library would be just as good, while not contributing to the complexity of JavaScript itself.

Note: it's related to this question, but here I'm asking about the "why", not the "how". I try to understand the motivations.

Community
  • 1
  • 1
mik01aj
  • 11,928
  • 15
  • 76
  • 119
  • 2
    `wrapToReturnPromise` is complicated (and often implemented wrong/overly naive) and incurs more overhead than necessary. An `async function` with `await` can be reasoned about and optimised better by the engine. – Bergi Mar 01 '17 at 18:03
  • 3
    Real power comes from having *both*: [async generator functions](https://github.com/tc39/proposal-async-iteration#async-generator-functions). That's just not possible with only generator syntax. – Bergi Mar 01 '17 at 18:05
  • 2
    `async/await` is not part of ES7 (ES2016)! It will be part of this year's release, ES2017. – Felix Kling Mar 07 '17 at 07:51

1 Answers1

8

At first glance, the syntax is similar and you might assume the code would behave similarly -- but there are some key differences:

  • Say what you mean: function* and yield mean something very different from async function and await, similar to how Subclass.prototype = Object.create(Superclass.prototype); Subclass.prototype.constructor = Subclass is different from class Subclass extends Superclass

  • Operator precedence: You can do await a + await b to mean (await a) + (await b), but yield a + yield b means yield (a + (yield b))

  • Future development: async/await pave the way for some really interesting work with optimistic transactional locking and speculative execution, since they are (as noted in this thread) explicit markers of atomicity boundaries

  • Other arguments: There are also many counter arguments to async/await -- including many people that say that generators are just plain 'better' and that async/await is going in the wrong direction.

Summarized shamelessly from the ES discussion site. I encourage you to read the entire thread as it has some very interesting discussion on the subject.

mik01aj
  • 11,928
  • 15
  • 76
  • 119
Dan Esparza
  • 28,047
  • 29
  • 99
  • 127