18 ms·
Cancelable Promises: Why was this proposal withdrawn?
- taneq 10y agoI'm not really familiar with the backstory here but it sounds like domenic was being seriously pressured/coerced to drop the proposal. What happened?
- stavros 10y agoIt sounds to me like most of the other people were disagreeing with him.
- egeozcan 10y agoIt was a case for practicality, versus the (for the lack of a better word) perfectionist arguments from the other side. I disagree with none of them but I think the discussion was a bit too intense.
- mikeryan 10y agoCan't tell if "most" or "small group - but enough" people.
- taneq 10y ago"vocal minority"
- dchest 10y agoDiscussion on Twitter: https://twitter.com/andrestaltz/status/809521268332593152 https://twitter.com/andrestaltz/status/809521268332593152
- semi-extrinsic 10y agoFor anyone else left clueless by title: a proposed new feature for JavaScript, as in ECMA TC39, was "cancellable promises", trying to handle "cancellation" of async actions ("promises") by extending normal try-catch structures with a "canceled" case. Due to unspecified internal Google drama, this (presumably popular) proposal has been withdrawn. Here are some slides with technical details of the proposal: https://docs.google.com/presentation/d/1V4vmC54gJkwAss1nfEt9ywc-QOVOfleRxD5qtpMpc8U/mobilepresent?slide=id.gc6f9e470d_0_0 https://docs.google.com/presentation/d/1V4vmC54gJkwAss1nfEt9...
- zoeysaurusrex 10y agoSo, I'm not saying they were wrong or right, but this is interesting to see what happens when the "consensus" is a major corporation. I'll make a prediction now. We'll be seeing things like this happening in the Microsoft code base in a few years. I'm a huge fan of Microsoft and their open source effort, but I'm not above believing that corporate interests win in the end. EDIT: Thanks for the downvotes, care to explain where I'm wrong? I'm sharing something called an opinion.
- aaron-lebo 10y agoIt's kind of funny to be in a world where Microsoft gets the benefit of the doubt (the 90s are rolling over in their graves). I'm a huge fan of Microsoft and their open source effort, but I'm not above believing that corporate interests win in the end. You can save yourself some suspense: yes corporate interests win. That's a result of a business model where corporations serve faceless shareholders. You are either making money or you aren't. The corporation is a soulless entity that workers and money pass through. This seems like pretty common human behavior, no? On a less cynical note, this kind of behavior is why a language designed by a bunch of corporations (JS) seems less and less interesting. Good luck practically influencing development if you aren't embedded in an organization already.
- zoeysaurusrex 10y agoOh yeah, I'd count project.json in dotnet core to be an example of that already. The community was told it would be pulled eventually with no real involvement from the community. EDIT: Or just robo-downvote me, lol instead of presenting a counterpoint.
- hvidgaard 10y agoIt was not like they didn't have a reason. The project.json was completely incompatible with the rest of their build chain, and changing it would be a colossal undertaking, that would mean they had to support two different build systems to remain backwards compatible. I'm not in favor of the msbuild system at all, it's not good. But it works, it's reasonable once you learn it (like most other build systems), and since they're footing the bill and have to keep the entire system in a coherent state, they decided what they did. The only reason we saw it, was that they've opened up their development process a lot earlier than they used to do.
- dreeko_ 10y agopromise for cancelable promises has been cancelled, how poetic
- paradite 10y agoAnd the author unsubscribed from the subject. Context: https://github.com/tc39/proposal-observable/pull/97 https://github.com/tc39/proposal-observable/pull/97
- nraynaud 10y agowas it an actual mid-computation cancellation with collaboration from the VM? I have done some heavy computations in JS, and it's a nightmare: your workers can be killed (I guess it's the browser saving resources) without any even escaping them, and webGL is always blocking the main thread (I had to chunk my computation myself).
- explorigin 10y agoNo it's for I/O ops. Think cancelling a fetch() like you can do with XHR.
- nraynaud 10y agoah! that seem like the easy stuff.
- ralfn 10y agoBut fetch() returns a promise, rather than a handler you can use to cancel the request. So some people wanted to add "cancel" as a third potential state of a promise. Which smells a bit like a hack to me. Why stop at cancel? The Fetch API shouldnt return a promise, maybe? But im assuming a lot of people gave it a lot of though. Maybe it is common enough. Maybe it is horrible to implement in a performant way. But so far the new ES features ive seen should have been critisized more not less. Look at the ugly mistakes that did make it: f => { pizza } Is the block on the right a statement block or an object literal? Its a statement block so if your lambda function returns an object literal than you need to wrap it in a statement block with a return statement. If it is anything else, than you dont. Thats the horrible crap that actually gets through the proccess. Imagine how naive and broken the propositions must be that get killed?
- EvilTerran 10y ago> if your lambda function returns an object literal than you need to wrap it in a statement block with a return statement Or you can just parenthesise the object literal: >>> (x => ({ x }))(23) Object { x=23 } The grammatical ambiguity is unfortunate, sure, but the simplest work-around isn't so bad.
- trungaczne 10y agoI suppose this is related? https://github.com/tc39/proposal-observable/pull/97 https://github.com/tc39/proposal-observable/pull/97
- cwmma 10y agoPromises have always been extremely contentious in JS for a couple reasons and Domenic has had the patience of a saint getting the original proposal through so it's totally understandable that he might not want to deal with this anymore especially if people in his org are against it. There were a couple reasons the original promises were so contentious to standardize. - Monads: there was a very vocal faction on TC-39 that really wanted a Promises to be monadic and very much emphasized mathematical purity over usefulness and any attempt to discuss things tended to get side tracked into a discussion about monads, see brouhaha over Promise.cast [1]. - Error handling: Promises have a bit of a footgun where by default they can swallow errors unless you explicitly add a listener for them. As you can theoretically add an error listener latter on all other options had downsides (not always obvious to advocates) leading to a lot of arguing, must of it after things had shipped and realistically couldn't be changed. Fixed by platforms and libraries agreeing on a standardization of uncaught promise events [2]. - Just an absurd amount of bike shedding probably the 2nd most bike shedded feature of the spec (behind modules). So cancelable promises reignite all the old debates plus there's no obvious right way to do it, like should it be a 3rd state which could cause compatibility issues and would add complexity, or should cancellations just be a sort of forced rejection, which would be a lot more backwards compatibility but with less features. Additionally there is a bizarre meme that somehow observables (think event emitters restricted to a single event or synchronous streams that don't handle back pressure) are a replacement for promises or are a better fit for async tasks they should be used instead. edit: patients => patience 1. https://esdiscuss.org/topic/promise-cast-and-promise-resolve https://esdiscuss.org/topic/promise-cast-and-promise-resolve 2. https://gist.github.com/benjamingr/0237932cee84712951a2 https://gist.github.com/benjamingr/0237932cee84712951a2
- TheAceOfHearts 10y agoPromises work fine in some cases, but absolutely I hate how exceptions and errors are grouped into the same bucket. Oh, you're handling 4XX responses as errors? Well, now you get exceptions there as well, good luck! e.g. If I'm sending some data over the network, I want runtime errors to cause activity to be aborted and logged. But if I get a 429, I'll want to wait and retry.
- kbody 10y agoCases like these show how needed transparency is (see Mozilla). Hopefully this will cause Google to open up some more (although doubt it).
- Klathmon 10y agoThey are being transparent, there is a scheduled meeting of everyone involved in january. And using this comment to rant a bit, I hate the idea that just because information isn't being announced immediately after someone finds out about something means that you aren't being "transparent". In this case, this was most likely discussed internally, and come jan they will present the results on why it was canceled giving insight into the why and perhaps it's replacement or their ideas moving forward. Now if come january it's just said "it's canceled" and nothing more, then i'll be right there with you calling for transparency and more discussion on the reasons, but you need to give the people involved a chance to actually have that discussion.
- ralfn 10y agoBut we already got our pitch forks out and everything!
- moron4hire 10y agoThe reason they have to have the announcement is because they discussed this and made the decision themselves in a non-transparent way. Or if that's not your definition of transparent, then what we want is more than just mere transparency. We want open discussion. I'm getting sick and tired of "open source" only happening when Google says so.
- deleted 10y ago[deleted]
- mcguire 10y agoThe proposal has been withdrawn. Why would it be on the agenda in January?
- 10y ago
- BigJono 10y agoCan someone give a good use case for these that can't be easily solved with existing tools? I'm really struggling to find a good example. I seem to have this problem for a lot of new stuff introduced into Javascript...
- skylark 10y agoWhy should you be satisfied with using tools? If the feature is compelling enough, it should be included in the standard library.
- Klathmon 10y agoBecause a tool can be replaced, it can be upgraded, it can have multiple competing implementations that will work across browsers and even languages. Tools can be easily deprecated, removed, changed, fixed, and improved. Tools can be made much simpler and faster by only supporting a single use case, or they can be slower and more complicated but solve them all. Language features are much more set in stone, mostly because breaking backwards compatibility in a language implementation is not something to take lightly. You don't have the option of only supporting a subset of a feature for a massive speedup, it's all or nothing (for an example of this, see benchmarks between the native .forEach and alternate implementations which are much faster but cut some corners). JS is still feeling the pains of mistakes made in it's early days, and throwing more features which aren't fully thought out into the language is a recipe for disaster. (This does not mean that I think every feature added to JS is perfect, or even warranted. It's just the reasoning for not trying to add some features which could be better addressed with tooling)
- skylark 10y agoFair point. Thanks for your input.
- xyzzy123 10y agoI might be talking past you here, but I think promises definitely qualify as a language feature for JS. Promises get baked deep into API signatures. Getting the tradeoff wrong leads to the horror of e.g, the situation for years in c++ where every major library had its own competing string class. Even if std::string was not the best possible string class of all possible string classes, just being able to call all the things without wrapping or thunking or templating everything fixed a major source of pain. We have already seen this in JS to some extent with various libraries offered in versions supporting native or q or bluebird promises. Fortunately JS is a lot more forgiving than C++ in this respect due to its dynamic nature. Anyway, the fact that they will tend to appear somewhere in API signatures for any large library is why I support native promises as language feature, not tooling.
- leothekim 10y agoSerious question - why is cancelling a promise a reasonable use case? Doesn't cancelling potentially invite non-deterministic state into your program? If not, what would be the difference from throwing?
- detaro 10y agoThe presentation about the proposal linked in a comment above [0] and the proposal itself [1] explain the difference to an exception quite well [0] https://docs.google.com/presentation/d/1V4vmC54gJkwAss1nfEt9ywc-QOVOfleRxD5qtpMpc8U/mobilepresent?slide=id.gc6f9e470d_0_0 https://docs.google.com/presentation/d/1V4vmC54gJkwAss1nfEt9... [1] https://github.com/tc39/proposal-cancelable-promises/blob/0e769fda8e16bff0feffe964fddc43dcd86668ba/Not%20an%20Error.md https://github.com/tc39/proposal-cancelable-promises/blob/0e...
- daleharvey 10y agoI have been waiting for cancellable promises for a while primarily for cancelling long lasting fetch requests which is a very common thing to need. (Not really sure how to parse non determinism and throwing being related to cancelling promises)
- fareesh 10y agoWhat's a good existing way to deal with this use-case? Is there a useful library that wraps setTimeout / other logic to determine the quality of a user's internet connection in case of very poor connectivity (2G etc) ?
- fermuch 10y agoIn react native, NetInfo has an api to detect network changes and I use that to stop all my setIntervals and start again with a different set of args, including wait time before calling again.
- jdesjean 10y agoThe way to handle this case is to use Promise.race with 2 promises. The first promise is your logic. The second promise is rejected after a timeout. For more detail read the section "never calling the callback" from "you don't know js" book on "async" in chapter 3 https://github.com/getify/You-Dont-Know-JS/blob/master/async%20%26%20performance/ch3.md https://github.com/getify/You-Dont-Know-JS/blob/master/async...
- Raed667 10y agoI'm trying to understand why Google people don't want cancellable promises? Did I miss an explanation somewhere?
- pitaj 10y agoThey probably want some form of cancellable promises, but think that the semantics and syntax in this proposal were bad. I agree with that.
- antirez 10y agoAfter something like that I would leave the company, probably. If something you care so deeply encounters a very strong internal opposition, probably there is an unaligned design idea and is better to provide efforts where those are better accepted, because otherwise the same story is very likely to repeat. And you know... life is too short.
- zcdziura 10y agoI don't think this situation would be worth quitting one's job over. So you didn't get your way after arguing with your peers over it, it happens. As you say, life is short.
- titzer 10y agoThere are a lot of stakeholders in a large organization, and a change can sometimes elicit strong reactions from involved parties. In particular, in the JavaScript world, implementors are now also explicitly represented in standard process of new language features, since given some of the preexisting warts, there can be nontrivial interactions and many JS abstractions have holes in them. A lot of language features have been rejected for a lot of different reasons. To be fair, some really unfortunate language features have been _accepted_ that have had unforeseen interactions or implementation challenges. I could name half a dozen off the top of my head. Disclaimer: I work on V8 but was not involved in this saga at all. I don't know which Googlers in particular Domenic is referring to in his comment. And of course I make no judgment on the particular value of cancelable promises.
- k__ 10y agoFunny thing is, they didn't stop it because it was Bad, but because some ppl at Google didn't want it. (probably because it was Bad, but it's sad to See that one company has so mich power)
- cloverich 10y agoBased on the comments in the linked thread, its sounds as if all participating companies have that same veto power. The justification seems to favor filtering false positives over false negatives in a sense. I suppose I can agree with that.
- k__ 10y agoYes. Getting crap into the language is worse than not getting good stuff in. But did they really veto here? As I read a few days ago, the guy doing the proposal just was forbidden by Google to work on it anymore. I wasn't in favor of this proposal think it's one of the better outcomes, but the form how if came to be dropped was a bit strange.
- nobleach 10y agoThis is what I'm seeing. I wasn't really a supporter of the feature... but I wasn't going to try and tear it down. Google has limited resources, so, since they didn't see any usefulness for their business model, they shot it down. They've instead chosen to throw some resources into evangelizing AMP - a technology that I hope dies quickly.
- wodencafe 10y agoIt sounds like some Google employees on TC-39 had significant resistance to the idea, and it is worrisome that employees of a private company can block proposals in favor of "their" way, in what is supposed to be an open and transparent Technical Committee, for a language that is supposed to be for all of us. Google trying to strong-arm control of JS for themselves.
- 0xCMP 10y agoI like to complain about big companies too, but Google isn't trying to strong arm control of JS. They hire a lot of smart programmers with strong opinions who express them and it seems like a lot of those were vocal enough to make this happen. Just how it is.
- wodencafe 10y agoIt's only a coincidence that the most vocal opponents to this proposal each receive a paycheck from Google? I'm starting to wonder why these TC's have so many Google employees, and you can claim it's because "they hire a lot of smart programmers", but the ratio of Googlers to not is way too high to represent the web development community as a whole - the majority of whom do NOT work for Google.
- mcguire 10y agoAnd did so behind the scenes within Google rather than in public?
- wodencafe 10y agoRight, this exactly. Also, why is every response with a hint of negativity towards google getting down voted? If Google was doing the right thing, they wouldn't have to be shielded from online criticism.
- 0xCMP 10y agoBecause clearly right now isn't when the transparency is going to come. It might come soon. If we don't hear anything then yes that's a problem, but clearly even the person who wanted this proposal doesn't want to talk. This does not appear to be avoiding transparency, but just some people had a VERY heated discussion about this and are burnt out. Mine you, I'm a big user of Go for personal projects and so I've seen Google make it's unilateral decisions before. I just don't think this is one of those situations.
- batmansmk 10y agoStill, the debate doesn't happen publicly. I don't know why and who opposes it. Google has no position in it. But someone undisclosed with sufficient power at Google opposes it. And does'nt share his point of view with the community...Sad day for open source.
- BinaryIdiot 10y agoIt's typically written up in meeting notes and someone publishes them if it happens during a meeting. If it happens outside of a meeting it likely happened in GitHub or the ECMAScript mailing list. The person(s) opposing have likely already shared their view point with the community at different stages. Proposals are not simply created and championed with zero feedback from the ECMAScript folks util they're proposed at a meeting.
- codedokode 10y agoCancellation can be implemented with another promise passed into cancelable function as an argument. This way it is easier to see that asynchronous function is cancellable. And Promise implementation would become simpler.
- strictfp 10y agoSounds like MIT vs Worse is Better
- dcarmo 10y agoIt would've certainly helped to avoid this: https://facebook.github.io/react/blog/2015/12/16/ismounted-antipattern.html https://facebook.github.io/react/blog/2015/12/16/ismounted-a...
- wycats 10y agoTC39 member here. cwmma gets a lot right here: Promises have always been contentious in JS (and TC39) and Domenic has indeed had the patience of a saint attempting to wrangle the various points of view into a coherent proposal. TC39 as a group is generally very motivated to find positive-sum outcomes and find solutions that address everyone's constraints in a satisfactory way. That doesn't usually mean design-by-committee: champions work on a coherent design that they feel hangs together, and the committee provides feedback on constraints, not solutions. As a member of TC39, I'm usually representing ergonomic concerns and the small-company JavaScript developer perspective. I've had a lot of luck, over the years, in giving champions my perspective and letting them come back with an improved proposal. The staging process (which I started sketching out on my blog[1]) has made the back-and-forth easier, which each stage representing further consensus that the constraints of individual members have been incorporated. Unfortunately, I fear that promise cancellation may be a rare design problem with some zero-sum questions. It's worth noting that there has been no objection, on the committee, to adding cancellation to the spec in some form. The key questions have been: First. Is cancellation a normal rejection (a regular exception, like from `throw`) or a new kind of abrupt completion (which `finally` would see but not `catch`). The current status quo on the committee, I believe, is that multiple people would have liked to see "third-state" (as Domenic called it) work, but the compatibility issues with it appear fatal. Second. Should promises themselves be cancelled (`promise.cancel()`) or should there be some kind of capability token threaded through promises. What that would look like: let [sendCancel, recvCancel] = CancelToken.pair(); fetchPerson(person.id, recvCancel); async function fetchPerson(id, token) { // assume fetch is retrofitted with cancel token support let person = await fetch(`/users/${id}`, { token }); } // when the cancel button is clicked, cancel the fetch cancelButton.onclick = sendCancel; This approach had many supporters in the committee, largely because a number of committee members have rejected the idea of `promise.cancel()` (in part because of ideological reasons about giving promise consumers the power to affect other promise consumers, in part because of a problem[2] Domenic raised early about the timing of cancellation, and in part because C# uses cancel tokens[3]). In practice, this would mean that intermediate async functions would need to thread through cancel tokens, which is something that bothered me a lot. For example, it would have this affect on Ember, if we wanted to adopt cancel tokens: // routes/person.js export default class extends Route { async model(id, token) { return fetch(`/person/id`, { token }); } } In other words, any async hook (or callback) would need to manually thread tokens through. In Ember, we'd like to be able to cancel async tasks that were initiated for a previous screen or for a part of the screen that the user has navigated away from. In this case, if the user forgot to take the cancel token (which would likely happen all the time in practice), we would simply have no way to cancel the ongoing async. We noticed this problem when designing ember-concurrency[4] (by the venerable Alex Matchneer), and chose to use generators instead, which are more flexible than async functions, and can be cancelled from the outside. At last week's Ember Face to Face, we discussed this problem, and decided that the ergonomic problems with using cancel tokens in hooks were sufficiently bad that we are unlikely to use async functions for Ember hooks if cancellation requires manually propagating cancel tokens. Instead, we'd do this: // routes/person.js export default class extends Route { *model(id) { return fetch(`/person/id`); } } The `*` is a little more cryptic, but it's actually shorter than `async`, and doesn't require people to thread cancel token through APIs. Also notable: because JavaScript doesn't have overloading (unlike C#), it is difficult to establish a convention for where to put the cancel token ("last parameter", vs. "the name `token` in the last parameter as an options bag" vs. "first parameter"). Because cancellation needs to be retrofitted onto a number of existing promise-producing APIs, no one solution works. This makes creating general purpose libraries that work with "promise-producing functions that can be cancelled" almost impossible. The last bit (since I started talking about Ember) is my personal opinion on cancel tokens. On the flip side, a number of people on the committee have a very strongly held belief that cancel tokens are the only way to avoid leaking powerful capabilities to promise consumers. A third option, making a new Task subclass of Promise that would have added cancellation capabilities, was rejected early on the grounds that it would bifurcate the ecosystem and just mean that everyone had to use Task instead of Promise. I personally think we rejected that option too early. It may be the case that Task is the right general-purpose answer, but people with concerns about leaking capabilities to multiple consumers should cast their Tasks to Promises before passing them around. As I said, I think this may be a (very, very) rare case where a positive-sum outcome is impossible, and where we need, as a committee, to discuss what options are available that would minimize the costs of making a particular decision. Unfortunately, we're not there yet. Domenic has done a great job herding the perspective cats here, and I found his presentations on this topic always enlightening. I hope the committee can be honest enough about the competing goals in the problem of cancellation so that Domenic will feel comfortable participating again on this topic. [1]: https://thefeedbackloop.xyz/tc39-a-process-sketch-stages-0-and-1/ https://thefeedbackloop.xyz/tc39-a-process-sketch-stages-0-a... [2]: https://github.com/tc39/proposal-cancelable-promises/issues/8 https://github.com/tc39/proposal-cancelable-promises/issues/... [3]: https://msdn.microsoft.com/en-us/library/dd997289(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/dd997289(v=vs.110).... [4]: http://ember-concurrency.com/#/docs http://ember-concurrency.com/#/docs
- novaleaf 10y agoI use Promises extensively, including cancellations (via the bluebird library) and find the following to be strong reasons not to ever use them, if they are to be implemented in a similar way that Bluebird uses them: 1) forward propagation side effects: canceling a promise doesn't mean rejecting. it means that further .then() or catch clauses are not invoked. This breaks (imo) a fundamental tenant of promises. 2) backwards propagation side effects: if you are waiting on a promise and cancel it, this is causing the previous promises in the chain to suddenly stop processing, again without any rejection, it just stops. 3) simple workaround: I don't think it is appropriate to backwards propagate promise cancellation, but it is very easy to emulate cancellation for downstream users (those using your promise). simply attach a "pleaseAbort=false" property to your promise and if a downstream caller wishes to cancel, they set .pleaseAbort=true and you can stop your processing and return a rejected promise.