tc39 / proposal-cancelable-promises

Former home of the now-withdrawn cancelable promises proposal for JavaScript
Other
375 stars 29 forks source link

You don't need `throw cancel` or whatever such syntax #10

Closed NekR closed 8 years ago

NekR commented 8 years ago

I sort of see the point with it, but thing is, we don't need cancelation outside of promises. Even for async/await it's still about promises. So:

In my mind, how it should be for Promises:

Instead of

const canceledPromise = Promise.resolve().then(() => {
  throw cancel new CancelReason("the user clicked 'stop'");
});

Use

const canceledPromise = Promise.resolve().then(() => {
  return Promise.cancel(new Error("the user clicked 'stop'"));
  // or just Promise.cancel("the user clicked 'stop'");
});

And how it should be for async/await:

async function Z() {
  if (something) {
    return Promise.cancel(...);
  }
}

Not really elegant for async/await, but it's way better than introducing new lang keyword just for that.

ljharb commented 8 years ago

I see plenty of use cases for cancellation outside of promises - breaking a loop early, for example, or simply using it as a third branch of flow control.

Just like throw is the syntactic form of return Promise.reject(), return Promise.cancel() needs a syntactic form too.

NekR commented 8 years ago

breaking a loop early

break, return?

Just like throw is the syntactic form of return Promise.reject(), return Promise.cancel() needs a syntactic form too.

There is already cancel for function: return. Promises evolved as a feature over JS and then async/await evolved on top of that.

Just like throw is the syntactic form of return Promise.reject()

That is wrong, Promise.reject() only has one meaning -- reject promise. throw has many of them now (throw exception, reject promise), but originally it was for exceptions. throw mutated to have meaning of Promise.reject() too, but it's not a syntactic form of Promise.reject(). What is syntactic form of Promise.resolve() then?

What you want now, is to mutate language itself because something is added to promises. That's wrong. Cancelation makes sense only in terms of Promises or other async flow (which doesn't exists in JS at a moment), but you want to add it into canonical throw. Don't do this.

NekR commented 8 years ago

EDIT: DELETED. Wrong issue.

NekR commented 8 years ago

Okay, resolve() is kind if equivalent of return. Still, there is no point to have syntax for cancelation. throw behaves like rejection because it was there before Promises and it had to behave somehow. It would be weird if it was doing nothing. In the end of a day, throw something is the same as return Promise.reject(something) (in promise handlers/async functions).

Even though you may want this (I don't know why though):

for (let key of something) {
  if (!otherThing) {
    throw cancel new Error();
  }
}

it's only valid in in promise handlers/async functions which is super weird has no sense. What it will do in normal function? return new Error()?

ljharb commented 8 years ago

Everything Promises has, must have parallel syntax, and throw cancel would work everywhere, not just in promises or async functions.

NekR commented 8 years ago

Why it has to? What it will do outside of promises? What is the point of that? 26 Май 2016 г. 18:17 пользователь "Jordan Harband" notifications@github.com написал:

Everything Promises has, must have parallel syntax, and throw cancel would work everywhere, not just in promises or async functions.

— You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub https://github.com/domenic/cancelable-promise/issues/10#issuecomment-221901718

NekR commented 8 years ago

I am not an expert in parsing, but just BTW, how will you parse this:

function cancel(x) { alert(x) }

throw cancel(123);
Wuntenn commented 8 years ago

Been thinking about this. I'm still a bit green/stupid with JS in general so I thank you in advance for reading this if you do. Your example above actually is convincing that there is a problem but I don't think it's in the place where it seems to be.

As developers we've decided that anything that doesn't fit the anticipated flow of our must be an error. We baked into JS via our informal API's and constructs like throw/catch the idea all program flow must grant the answers right now in order to continue and they've been sufficient until now.

Timer trickery in the form of setTimeout and setInterval have allowed us to rescue intentional delays from being classified as errors. This has allowed us to prop up this lie in our agreed philosophy.

Promises are our attempt to recognise that delay may be a necessary evil. We now look to this promise object and ask if the outcome was good or bad once it's resolved. The thing is, in accepting promises and the idea of time into the program flow, our lie slowly begins to unravel and we must decide how to tell a better lie, or how to tell the truth to our code!

Cancelling isn't an error. Calling it one however, does make the code more readable as seen in your example. The potential downside is that we may wish to treat a cancel in a similar way to an error letting it propagate and be handled further up the call-stack/chain. Along these lines of thinking cancel is something we should keep (unless we want to continue to lie).

When we look at the whole picture it looks like cancel will rear it's head in (most but not all of) the same places errors will. Right now that's fine because there's just the two of them 'error' and 'cancel'.

However:

If promises are what happens when we know that some result good or bad will come moments later. We can deduct that asynchronous web apps have forced us to admit this to construct to our code. We can try to anticipate how escalating trends now may force us to tell the code more/new truths in the form of future changes to the language. Maybe for cases where:

navigator.serviceWorker.register('/sw.js').deferr({ date: 'somedate'}).then()

I'm just guessing about these two extra types but we can see how messy things would get if we added similar changes for new types like this into code. Things could start looking like:

Promise.resolve().then().catchCancel().CatchDeferred().CatchTransfer().CatchOtherNewTypeToBeInvented().catch();

That seems wrong! If we look at were they occur, they also are likely to occur around the same places where we currently handle errors. Stepping back to look at all of them we see that the game has changed slightly. We're no longer just looking for errors. What we are looking for is really inflection points in our program that cause the flow to change abruptly. Errors just happen to be one type of these.

Instead of anticipating, passing around, and testing for errors we should anticipate inflection points where the inflection would be an object similar to how errors currently exist. The inflection object would be an object containing handlers for the relevant flows. In code it would look like:

Promise.resolve().inflect(inflection).catch();

'inflection' would represent a configuration object that is used to handle the inflection. The use of catch above may not be needed because the inflection could handle it. It's strength would be restored in longer promise chains (and not watered down by the introduction of lots of types of catch). Initially the inflection point object would handle and have keys for error and cancel:

var inflection = { 
  error: (e)=>{  //handle error e },
  cancelled: (c)={  //handle cancellation c }
}

later it would/could contain types like above and would allow us to see and understand the code at a glance again. Thinking in this way we end up with a construct that acts like a junctions seen in typically in diagrams/UML to model the flow changes.

Changes to the language would simply mean we handle new things in the inflection point and the lie that all unanticipated changes are errors would be broken.

This would allow inflection points in code to be expressed declaratively without muddying the nice clean coding style that we're are all eagerly anticipating.

boopathi commented 8 years ago

Instead of a new keyword cancel, what about using <keyword>.<property> syntax like new.target ? throw.cancel & catch.cancel ?

NekR commented 8 years ago

@Wuntenn your essay about inflection sounds interesting and I have nothing against that. But as you say in it and Domenic in his Third State, it's not an error. It's kind of, abrupt completion of some time.

My point here is that it's bad to try solving cancelation with errors, even not directly. Solving cancelation with errors-like-syntax is wrong, even without throw cancel which is absolute disaster.

Still, I don't get where I misuse cancelation here, because I not use it at all. I just remodel given examples to better ones (in my mind).


Another thing is that it actually might be fine to go cancelation is error route. i.e. I, as web/JS developer, would be perfectly fine with cancelation being CancelError rejection. Why?

Thinking of it more, I think cancelation should be just and error type. It will handle anything, even inflection proposal, which actually exceptions/errors are.

Hell, it can be easily polyfilled for old implementations too.

Wuntenn commented 8 years ago

Sorry about the essay! :D:D @NekR For the same reasons that:

function error(x) { console.log(x) }

wouldn't allow you to handle errors which require use of a try {} catch {} instead, you also wouldn't be able to handle cancelled events with your function above.

To handle cancels you would need a catch that works specifically with cancels. This is catchCancel() I suspect tryCancel is on the way also. I can see why @boopathi suggests try.error and try.cancel.

I personally see the solution along the same lines as both of you with try and catch acting like switch:

try {
  functionThatCouldCancelOrErrorOrDoSomethingElseInTheFuture()
} catch {
  error(e) {
   //handle error here   
  }
  cancel(c) {
   //handle cancellation here
 }
 somethingElseInTheFuture(s) {
   //handle whatever here
 }
}

Like you I don't want to have to remember a million new conventions. Something like this would be understandable and a small change from how we do things now. We stop anticipating errors and see this as handling an inflection point.

domenic commented 8 years ago

throw cancel is a core part of this proposal, although the syntax will need to change since it is not OK. I will open a new issue for that.

The reasons for this are outlined in https://github.com/domenic/cancelable-promise/blob/master/Third%20State.md. I get the impression, perhaps mistaken, that many people here have not read that, despite it being in the repo they are creating issues on.

Another source that may be edifying is the original "You're MIssing the Point of Promises" essay that explains the importance of the sync <-> async correspondence.

To summarize: the core of this proposal is a third state, which necessarily drags along with it a number of syntactic affordances. As such, I'd like to close this issue in favor of two new potential issues:

But this issue's original question, of whether a syntactic form to create completions representing the third state is necessary, can be answered in the affirmative: yes, it is. I'm happy to continue discussing why that is if it's not clear to people after reading the two links I provided above, but I'm going to close the issue and we can continue discussion in the closed issue, since I don't consider this an open issue with the proposal or something that could possibly ever change unless the third state concept is abolished (which, as I said, would be a different issue).

benjamingr commented 8 years ago

I don't think it needs throw cancel syntax because it propagates the other way around, I would do myPromise.cancel from the outside. That doesn't take anything away from the Third State document which I completely agree with.

ljharb commented 8 years ago

@benjamingr it makes promises mutable, and "immutable from the outside" is something many consider to be a core property of promises. (throw cancel would apply to the new promise being created by the then, and not to the promise it was chained off of)

NekR commented 8 years ago

@domenic

But this issue's original question, of whether a syntactic form to create completions representing the third state is necessary, can be answered in the affirmative: yes, it is.

So this is why you closed this issue, because you think answer is yes? Is this how you do standards, when someone starts discussion you just say "it should be" and close issue? I answer is title confuses you, I can rename it to affirmation -- you don't need throw cancel (or whatever such syntax).

I made a lot of examples why it's bad, a lot of alternatives, etc. And what you got from you: "You don't understand parsers so don't write here. And btw, yeah, we need this syntax". Nice explanation.

inikulin commented 8 years ago

@NekR Problem with return Promise.cancel() is that it doesn't propagate, e.g. you need to cancel whole promise chain:

Promise.resolve()
.then(()=> {
     throw.cancel new CancelReason('yo!');
})
.then(doSomething)        // Nothing should happen here
.then(doSomethingElse) // Nothing should happen here either

You can argue that we can add special semantics for Promise.cancel as a return value, so it will enable propagation of cancel reason and therefore cancel whole promise chain. But it really violates existing semantics of return. Cancellation behaves like rejection, but with exception that it can be unhandled and not treated as error which makes it third state. And this third state doesn't have any parallels in the existing sync semantics (like we have e.g. for rejection). This is completely new. We need explicit syntax for new semantics - otherwise, it will be a huge source of confusion.

About throw.cancel in sync code. The thing is that you can't tell ahead of time if code will be executed in Promise chain context. E.g.:

function someFunc() {
    throw.cancel new CancelReason('yo!');
}

someFunc(); // Sync

Promise.resolve().then(someFunc); //In Promise
NekR commented 8 years ago

@NekR Problem with return Promise.cancel() is that it doesn't propagate, e.g. you need to cancel whole promise chain:

Why it doesn't propagate? Promise.reject() propagates fine here:

Promise.resolve()
.then(()=> {
     return Promise.reject(123)
})
.then(doSomething)        // Nothing happens here
.then(doSomethingElse) // Nothing happens here

And Promise.cancel() 'll is the same same, except that it's third state. No need to specially treat return or any other syntax. It's handled at runtime, as with Promise.reject().

About throw.cancel in sync code. The thing is that you can't tell ahead of time if code will be executed in Promise chain context. E.g.:

Exactly. And what it will do in someFunc(); // Sync case? What will happen inside function?

benjamingr commented 8 years ago

@inikulin

Promise.resolve()
.then(()=> {
     throw.cancel new CancelReason('yo!');
})
.then(doSomething)        // Nothing should happen here
.then(doSomethingElse) // Nothing should happen here either

Why would I ever do something like that (the throw cancel)? I cancel things from the outside not from the inside. If we look at all the actual use cases I don't really see what throw.cancel would be used for.

NekR commented 8 years ago

@benjamingr I agree that real use case is fetch().cancel(), but this repo seems to be about how to handle cancelation only, without taking in account how to invoke them. And it's weird because one depends on another anyway.

NekR commented 8 years ago

@inikulin did you mean throw.cancel new CancelReason('yo!'); should propagate up? Because everything propagates down, buy key thing with cancelation is to cancel upper things, e.g. this:

fetch().then(() => {
  if (something) {
    throw.cancel new CancelReason('yo!');
  }
});

This has to cancel fetch() request, right? But it's indeed super weird to cancel Promises by this way. Everyone will have this then:

Promise.prototype.cancel = function() {
  return this.then(() => { throw.cancel new Error('I wanna cancel') });
};

Nice usage for new syntax.

inikulin commented 8 years ago

I agree that real use case is fetch().cancel(), but this repo seems to be about how to handle cancelation only, without taking in account how to invoke them.

Why would I ever do something like that (the throw cancel)? I cancel things from the outside not from the inside. If we look at all the actual use cases I don't really see what throw.cancel would be used for.

You will be able to cancel promises from the outside, but not by promise.cancel. promise.cancel brakes immutability of the promises as @ljharb pointed above. Instead it's proposed to use cancellation tokens for this purpose. While cancellation tokens give you mechanism to notify promises about cancellation, to propagate cancellation you will use throw.cancel. throw.cancel is just a part of this mechanism. However, I see use cases there you can use throw.cancel without tokens, then promise will decide that following chain doesn't required anymore.

inikulin commented 8 years ago

This has to cancel fetch() request, right?

No, it propagates like error.

inikulin commented 8 years ago

The whole point of current API is to build cancellation logic on downward error-like propagation, because upward propagation breaks promise immutability.

NekR commented 8 years ago

No, it propagates like error.

Why it need then? What it does what return Promise.cancel() cannot?

You will be able to cancel tokens outside, but not by promise.cancel

This repo about how it will be handled, they don't want to talk about how cancelation will be invoked. We were talked about in in whatwg/24 for months and nothing happened expect of this. So don't say "it will use token", no one decided that yet.

inikulin commented 8 years ago

Why it need then? What it does what return Promise.cancel() cannot?

return value goes to the next then in the chain as an argument

So don't say "it will use token", no one decided that yet.

As far as I understand this is currently working model of how it will be triggered. But if you wish I will not mention tokens anymore if it's somehow makes you satisfied =)

benjamingr commented 8 years ago

Cancellation on promises doesn't break their immutability we've had it in bluebird 3 for a year - a promise never transitions after it settled - cancellation is just a "third state".

Once a promise is fulfilled cancelling it is a no-op, if it is cancelled it settles as cancelled and that's it. Immutability invariants are preserved.

While cancellation tokens give you mechanism to notify promises about cancellation, to propagate cancellation you will use throw.cancel.

So this is supposed to mainly be used in catch cancel blocks to notify that a promise is still cancelled? Are we even allowing "recovering from cancellation"? Is that still a thing?

All I'm asking for at this point is a single use case where in a real world example throw.cancel is useful - I can find at least a dozen for cancellation in general but not a single one where I'd use throw.cancel

NekR commented 8 years ago

return value goes to the next then in the chain as an argument

Promise.reject() value doesn't go to next then()'s first argument, it goes to the second. Same Promise.cancel() will go to the third handler of then(). Or you mean that throw.cancel will bypass all the handlers, e.g. catchCancel() too?

inikulin commented 8 years ago

Cancellation on promises doesn't break their immutability we've had it in bluebird 3 for a year - a promise never transitions after it settled - cancellation is just a "third state".

Really?

var promise1 = doSmthg();
var promise2 = promise1.then(doSomethingElse);

promise2.cancel(); // Should it cancel only last promise in the chain to make statement in the next line true?

await promise1; // With immutable promises this should be resolved
inikulin commented 8 years ago

Promise.reject() value doesn't go to next then()'s first argument, it goes to the second

OK, I understand your point now. But if you expand it to async/await and even in promises itself: do you often use return Promise.reject() instead of throw Error?

benjamingr commented 8 years ago

@inikulin promises were never immutable - they are only immutable after they settle - this is fundamental.

let reoslve;
let p = new Promise(res => resolve = res);
// I can now mutate p as much as I want _once_

that's the invariant and it gets preserved. promise1 is either fulfilled or cancelled but never both.

NekR commented 8 years ago

do you often use return Promise.reject() instead of throw Error?

I, personally, all the time use Promise.reject(). Yes, I use some times throw ... but very rarely. But even if I was using throw ... all the time, throw.cancel doesn't worth. New syntax doesn't worth it.

inikulin commented 8 years ago

promises were never immutable - they are only immutable after they settle - this is fundamental.

I'm afraid I don't understand your point. Can you elaborate, please?

inikulin commented 8 years ago

New syntax doesn't worth it.

Is it just a personal feeling or there are some technical issues with it?

NekR commented 8 years ago

@inikulin personal feeling.

benjamingr commented 8 years ago

I'm afraid I don't understand your point. Can you elaborate, please?

A promise is not "immutable", the invariant is actually that a promise is immutable after it has gone settlement (that is, transitioning from the "pending" state to either "fulfilled" "rejected" or now "cancelled").

That is kept, if a promise fulfills cancelling it has no effect. This is a fundamental part of the design and the complete overhaul (and rewrite) of cancellation in bluebird 3.0 where cancellation signals disinterest (rather than an abortive state like rejection based cancellation).

inikulin commented 8 years ago

A promise is not "immutable", the invariant is actually that a promise is immutable after it has gone settlement (that is, transitioning from the "pending" state to either "fulfilled" "rejected" or now "cancelled").

Seems like you confusing eventual value with the promise itself. We are talking about immutability not in context of promise intrinsics, but the promise as value itself. Any operation on promise will produce new promise and operations consequent promises will not affect it's ancestor in the chain (yes you can do that by leaking resolve, reject, but we are talking about intended usage).

I took a look at Bluebird implementation and it's just bad, starting from the fact that cancel should be sync (there are numerous cases there graceful cancellation requires async operations).

From Bluebird docs:

Propagating the cancellation signal (and therefore making it abort the request) would be very bad as the second consumer might still be interested in the result despite the first consumer's disinterest.

Promise upper in the chain was cancelled. It just doesn't have any return value. This is just non-sense. Nevermind, I thought it has error-like propagation, but it's not.

What actually happens is that result keeps track of how many consumers it has, in this case 2, and only if all the consumers signal cancel will the request be aborted. However, as far as firstConsumer can tell, the promise was successfully cancelled and its handlers will not be called.

OMG, it's just breaks the whole promises concept. Promises upper in the chain shouldn't care about their consumer. This is what makes promises beautiful - at each point in the chain you have independent peace of functionality going which ends up with some eventual value.

benjamingr commented 8 years ago

If you're going to use terms like "non-sense" and "OMG" I'm not interested in having this discussion with you. I don't know what your background is but I warmly recommend that you:

a) Play a little with bluebird cancellation semantics (they don't do what your post implies you think they do at all - the whole point is that promises upper in the chain still don't care about their consumer). b) attempt to use language that does not mock other opinions, especially when we try to encourage collaboration in these discussions.

inikulin commented 8 years ago

If you're going to use terms like "non-sense" and "OMG" I'm not interested in having this discussion with you.

Sorry, I'm not a native speaker and didn't know that this phrases have any rude meaning.

Play a little with bluebird cancellation semantics (they don't do what your post implies you think they do at all - the whole point is that promises upper in the chain still don't care about their consumer).

As I said, I already have a scenario there this cancellation mechanism will not work: if cancellation process is async itself.

NekR commented 8 years ago

@benjamingr

So this is supposed to mainly be used in catch cancel blocks to notify that a promise is still cancelled? Are we even allowing "recovering from cancellation"? Is that still a thing?

All I'm asking for at this point is a single use case where in a real world example throw.cancel is useful - I can find at least a dozen for cancellation in general but not a single one where I'd use throw.cancel

I am not sure if it's a use case at all and I am still against throw.cancel, but here is what I came up with:

async function something() {
  try {
    try {
      await A;
    } catch.cancel(r) {
      if (!condition) {
        throw.cancel r;
      }
    }

    await B;
  } catch cancel(r2) {

  }
}

But it's hard to imagine why this could happen in real world.

inikulin commented 8 years ago

As I said, I already have a scenario there this cancellation mechanism will not work: if cancellation process is async itself.

My bad, I've figured out how it can be done with Bluebird semantics. But, it as far as understand it requires closure on promise itself and it's not applicable in some cases.

benjamingr commented 8 years ago

@inikulin please play with it for a few hours and come to your conclusions there - I don't think it breaks immutability guarantees and it handles cancellation well - there are cases where cancellation must by synchronous as well. This repository and issues are a good place to start reading about it.

Anyway, the issue here is not bluebird cancellation semantics (they were just an example). It's the invariants - if cancellation is based on disinterest then it makes absolute sense to not run onFulfilled and onRejected handlers.

Any cancellation scheme with promises (in addition to or instead of tokens) would require you to be able to call .cancel on a promise in one way or another.

Cancellation fundamentally travels upwards in the chain (that's its point) but with disinterest based cancellation you can't make trivially code run that would otherwise not run except maybe cleanup code.

benjamingr commented 8 years ago

@NekR so the use case for throw.cancel is only to be able to propagate inside catch cancel blocks?

Maybe I should take a step back - I don't really understand the motivation for onCancelled as a third then callback either vs. just using finally blocks to deal with cancellation. I understood they were added for symmetry since it is a third state but I wonder - why do we even need them?

What motivating examples are there for catch cancel that aren't handled by finally?

inikulin commented 8 years ago

Maybe I should take a step back - I don't really understand the motivation for onCancelled as a third then callback either vs. just using finally blocks to deal with cancellation. I understood they were added for symmetry since it is a third state but I wonder - why do we even need them?

It required if you want to perform some additional actions on cancellation, e.g. graceful cancellation. It might be distinct from what you want to do on rejection or on resolve. Also, you might want to stop cancellation propagation like we do for errors.

benjamingr commented 8 years ago

It required if you want to perform some additional actions on cancellation, e.g. graceful cancellation.

Care to share an example where I would use catch cancel and not finally to perform cleanup?

Also, you might want to stop cancellation propagation like we do for errors.

Why? Can I get a motivating example? I have no intuition for "stopping cancellation" - you can only prevent it from going "up".

inikulin commented 8 years ago

Care to share an example where I would use catch cancel and not finally to perform cleanup?

async function convertImagesToJpeg(files, cancelToken) {
   var writtenFiles = [];

   try {
       await Promise.all(files.map(async fileName => {
           cancelToken.throwIfRequested('Operation was rejected by user');

           const content = await readFile(fileName);
           const converted = await convert(content);
           const outFileName = await writeFile(content);

           writtenFiles.push(outFileName);
       }));
   }
   catch.cancel (reason) {
       // We need to delete already written files, since whole operation was cancelled.
       await deleteFiles(writtenFiles);
       console.log(reason);
   }
   finally {
        // Clean up any other stuff, e.g. if we produce some intermediate temp files during conversion
   }
}

Yes, you can check token.requested in finally, but with catch.cancel you have a sugar which makes code much cleaner.

Why? Can I get a motivating example? I have no intuition for "stopping cancellation" - you can only prevent it from going "up".

This is exactly what I mean, you stop it's propagation.

Wuntenn commented 8 years ago

I can see how together with .catchCancel() you would've had flexibility later on to capture this cancellation further up within a promise-chain if it had't been handled here.

Thanks for the example! (I was trying to think of a case where cancel would differ from finally).

This isn't so different from how we work right now. Think I like it! :D

domenic commented 8 years ago

So don't say "it will use token", no one decided that yet.

This was decided at the last TC39 meeting. Someone ill-advisedly tweeted some information from the meeting before I had a revised proposal ready, and told people to start filing issues on this repo before this repo fully reflected that meeting's consensus. So that is why there is a lot of confusion right now. Ideally people would have held off their judgment until a concrete proposal was ready for them to evaluate, but that clearly did not happen, so in the meantime I appreciate the efforts of people like @inikulin to try to clear things up, and would still urge people to hold off their judgement.

domenic commented 8 years ago

It seems there's a confusion caused by the use of the shorthand "immutable". Some committee members believe it's an important invariant that promises not be mutable by anyone but their creator; that is what is often meant by "immutable". @benjamingr hopefully you can see how introducing promise.cancel() breaks that invariant.

As I've said in the past, I don't find this invariant important, but any proposal which breaks it is a committee non-starter, and so unfortunately has to be abandoned.

inikulin commented 8 years ago

@benjamingr I would like to apologize for some of my comments here. Re-reading them now in peaceful settings I see how ignorant they are. Debugging and commenting on github in parallel makes me too irritable. Wouldn't do it again =)

benjamingr commented 8 years ago

@inikulin no hard feelings at all. I'll post a separate reply about the catch cancel example.

@domenic

This was decided at the last TC39 meeting. Someone ill-advisedly tweeted some information from the meeting before I had a revised proposal ready, and told people to start filing issues on this repo before this repo fully reflected that meeting's consensus.

I'm merely subscribed to this repo and am interested in this. I could not find the meeting notes yet - I did find (and read your presentation).

Ideally people would have held off their judgment until a concrete proposal was ready for them to evaluate, but that clearly did not happen, so in the meantime I appreciate the efforts of people like @inikulin to try to clear things up, and would still urge people to hold off their judgement.

In case it wasn't clear, I'm not judging anything (yet) - I'm only asking questions about it. If you would like time to update the repository I don't mind holding off the questions for as long as I need to. I am only here to try and help with this proposal - if you feel I am not being helpful I will gladly postpone my participation for as long as you would like.