Closed NekR closed 8 years ago
The proposed syntax is
try {
...
} catch (e) {
...
} catch cancel (r) {
...
} finally {
...
}
with of course other permutations allowed, such as omitting any of the three non-try
clauses, or switching around the order of catch
and catch cancel
.
There may be alternatives and we can leave this issue open to track such alternatives, but in general modifying existing grammars is very difficult, and catch
is one of the only escape valves we have to allow this. For example, something like
try {
...
} catch (e) {
...
} cancel (r) {
...
}
does not work, as it's equivalent to
try {
...
} catch (e) {
...
}
cancel(r);
{
...
}
So if there is a way to avoid using catch
when designing the syntactic construct for catching exceptions, it is not immediately obvious. I'd welcome suggestions from grammar experts (but would prefer to avoid speculation from those who aren't familiar with how to implement a parser). Probably the easiest thing to do would be to use an existing reserved keyword, but I can't think of any reasonable ones (try { ... } enum (r) { ... }
, lol).
Anyway, I think it's fine to generalize the meaning of "catch" as a word to including catching cancelations, and not just exceptions. Sure, in an ideal world starting from scratch, maybe we'd use something different. But given what we have to work with, it's not so bad.
I guess it will be catch.cancel
for consisteny if throw.cancel
will be a final syntax?
Maybe, although I am not a big fan of throw.cancel
. I plan to spend some time next week when I'm back to working on this full time trying to work through the possibilities for both syntaxes.
Have you considered else
as a reserved word option? Aborting an operation is essentially a conditional branch where the condition is deferred or asynchronous, and the universally understood and intuited complement to "if/then" is "else". catch
has such a strong association with error handling that building off of it feels more like a concession to the realities of parsing than the cleanest possible expression of the idea. In a perfect world, maybe we'd choose a slightly different word, but promises already use "then", and "else" goes right along with that.
try {
} else (x) {
} catch (e) {
}
if (!confirm(...)) {
else 'canceled';
}
fetch(...).then(...).else(...);
edit: Move else before catch.
That's a clever idea, but else
implies to me that it runs like finally
but only when no exception was thrown.
Why use such drastically new syntax? It seems like a more generally-useful approach would be to simply define a new global class CancelError extends Error
and then throw/catch that. Then if you really want new syntax, allow
try {
// 1
} catch (CancelError as e) {
// 2
} catch (e) {
// 3
}
This has an obvious desugaring by simply bundling all the catch
es together and going down the list of types
try {
// 1
} catch (e) {
if (e instanceof CancelError) {
// 2
} else {
// 3
}
}
Also as
is an already-existing contextual keyword with similar meaning in import
, so that also seems like a win.
Please read the contents of this repository, such as the readme or third state.md, to understand why cancelation is not a type of error.
I have read the contents. I suppose what I'm disagreeing with is your premise that cancellation is not a type of error. As you point out - it's certainly a lot closer in spirit to a rejection than it is to a resolution. You claim that it is "not exceptional" because the user or the programmer initiated it. But from the standpoint of the code that's running and expecting a value from its await foo()
call, exceptional is exactly what it is. I agree that it's awkward and burdensome to expect catch
blocks to check what type of exception they got, but it's equally awkward to not allows them to see the cancellations in the first place. The fundamental problem comes down to the fact that when I read } catch (e) {
, I have no way of knowing whether the developer meant "only deal with 'real' exceptions" or "no really, I want everything".
I would love to see cancelable promises land, but I worry that such drastic and breaking behavior change is infeasible and will prevent it from ever happening. A more conservative approach may be more tenable.
@shicks so basically you're saying that cancellations should not be caught by } catch (e) {
but are not rejections? I think that's just a renaming of the current proposal.
Cancellations are not rejections, even if they're closer to a rejection than to a resolution. I currently write a lot of code with cancellation in C# (where it is an error) and honestly it sucks really bad because I have to catch exceptions that are not cancellations everywhere.
catch cancel is gone so closing this.
As you said in https://github.com/domenic/cancelable-promise/blob/master/Third%20State.md, cancelation isn't a error, even thought it may look similar.
In JS,
catch
is used simultaneously with exceptions. So, if an Exception is raised--it can be caught. Cancelation doesn't raise exception and shouldn't.Plus, if you plan to add
try..catch..cancel..finally
it will be confusing, because it one place it's explicitly separated fromcatch
, in other place (Promise#catchCancel
) it hascatch
word in it.