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

Add a way to expose failing constructors #9

Closed
surma opened this issue Jun 20, 2017 · 8 comments
Closed

Add a way to expose failing constructors #9

surma opened this issue Jun 20, 2017 · 8 comments

Comments

@surma
Copy link
Contributor

surma commented Jun 20, 2017

From WICG discussion: Post 1, Post 2

TL;DR:

  • Not exposing when a constructor fails makes migrating existing code harder
  • Functions that usually can’t throw are usually not wrapped in a try/catch and now they need to be
@domenic
Copy link

domenic commented Jun 20, 2017

It's pretty strange, but it's actually possible to make a function (or proxy) such that

const x = await new Y();

works, and even to make const x = await Y(); fail. Sample:

function Y() {
  if (!new.target) {
    return Promise.reject("Illegal invocation");
  }
  return new Promise(r => {
    setTimeout(() => r(createActualY()), 1000);
  });
}

@domenic
Copy link

domenic commented Jun 20, 2017

I guess my concern with my above suggestion is that so far for async construction we've instructed people to use factory methods (e.g. window.createImageBitmap()) and this diverges from that precedent.

On the other hand these are pretty specialized objects, proxying from another thread, and not general web platform objects representing resources that need to be created async. So maybe it's OK for them to be special.

@surma
Copy link
Contributor Author

surma commented Jun 20, 2017

I actually think making await new X() work would be super consistent (“Just use await for everything that involves tasklets”).

I’d totally be down with that. @bfgeek WDYT?

@bfgeek
Copy link
Contributor

bfgeek commented Jun 20, 2017

Yeah I'm not sure... the argument against this in my head is that it's one thread bounce that we can easily remove, that 99.99% of the time isn't useful.

I.e.

a = await new api.A();
a.f1();
a.f2();

(two main->bg tasks).

vs.

a = new api.A();
a.f1();
a.f2();

(only one main->bg task).

@bfgeek
Copy link
Contributor

bfgeek commented Jun 20, 2017

I.e. multiple calls which we don't await can be batched up.

@surma
Copy link
Contributor Author

surma commented Jun 21, 2017

Developers can still batch if desired, no?

const [a1, a2, a3, a4] = 
  await Promise.all([
    new api.A(), 
    new api.A(), 
    new api.A(), 
    new api.A(),
  ]);

Another thing I realized:
Exceptions are (often) used for control flow. So if the implementation of a1.f1() throws for exactly one reason, the developer will probably react to an exception with what makes sense in the context of that exception. Without being able to detect constructor exceptions in isolation, the code can throw for two reasons, for only one of which the currently implemented exception handling is appropriate.

The more I think about it, the more I like the await new, despite being a new thing™️.

@surma
Copy link
Contributor Author

surma commented Aug 17, 2017

The polyfill now uses await new MyClass() and I think it’s more consistent. Gonna update the README and close this.

@surma
Copy link
Contributor Author

surma commented Aug 17, 2017

For completeness’ sake:

the argument against this in my head is that it's one thread bounce

The polyfill does it in one bounce. I’m sure a native implementation can do the same ;)

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

No branches or pull requests

3 participants