kneden icon indicating copy to clipboard operation
kneden copied to clipboard

Unnecessary extra tick

Open ljharb opened this issue 8 years ago • 4 comments

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.

ljharb avatar Apr 10 '16 22:04 ljharb

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).

marten-de-vries avatar Apr 17 '16 21:04 marten-de-vries

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

ljharb avatar Apr 18 '16 00:04 ljharb

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.

eliperelman avatar Feb 23 '17 13:02 eliperelman

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

ljharb avatar Feb 23 '17 19:02 ljharb