Skip to content
This repository has been archived by the owner on Jun 10, 2019. It is now read-only.

Unnecessary extra tick #47

Open
ljharb opened this issue Apr 10, 2016 · 4 comments
Open

Unnecessary extra tick #47

ljharb opened this issue Apr 10, 2016 · 4 comments

Comments

@ljharb
Copy link
Member

ljharb commented Apr 10, 2016

var foo = async () => {
  console.log(1);
  return (await 1) + 2;
}
foo();
console.log(2);

should transpile to:

var foo = function foo() {
  return new Promise(function (resolve) {
    console.log(1);
    resolve(1);
  }).then(function (_resp) {
    return _resp + 2;
  });
};
foo();
console.log(2);

which should log 1, then 2.

but instead transpiles to:

var foo = function foo() {
  return Promise.resolve().then(function () {
    console.log(1);
    return 1;
  }).then(function (_resp) {
    return _resp + 2;
  });
};
foo();
console.log(2);

This difference means the async function takes an extra tick - which results in logging 2, then 1.

@marten-de-vries
Copy link
Collaborator

Nice find, thanks for reporting.

There is the edge case of what to do with functions thrown before an await statement to take into account. It's some time ago I looked it up in the spec, but I think the correct behaviour is to make these too reject the promise instead of returning an error. That would make the total code required be something like this instead:

const PromiseChainStart = {
  then(func) {
    return new Promise(function (resolve, reject) {
      try {
        resolve(func());
      } catch (err) {
        reject(err);
      }
    });
  }
};

PromiseChainStart.then(function () {}
});

Doing it that way would also keep the code generation easier since there wouldn't be two return styles to handle (resolve/reject calls vs. return/throw).

@ljharb
Copy link
Member Author

ljharb commented Apr 18, 2016

@marten-de-vries it should reject the promise, and new Promise already has a try/catch, so no explicit one is needed.

@eliperelman
Copy link

I hadn't really thought of these semantics before, but curious: should 1 log before 2 if you aren't awaiting foo's call? I guess said another way, should there be a difference in logging the values if the code is:

foo();
console.log(2);

versus:

await foo();
console.log(2);

Apologies if this seems obvious, but I wanted to verify behavior.

@ljharb
Copy link
Member Author

ljharb commented Feb 23, 2017

Yes, the spec says that both examples should log 1 and then 2.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants