14 ms·
JavaScript Promises in Wicked Detail
- enraged_camel 12y agoThis is off-topic, but there seems to be this trend on HN (and probably similar sites) where a post about Topic X will get a lot of comments/views, and the following several days similar posts will appear on the front page, in the format of "Why You Should Never Do X" or "A Better Way to Do X". What I'm wondering is whether this is some sort of bias on my part (I tend to notice them because my memory of the original post is still fresh), or whether the subsequent stories are upvoted to the front-page because people want to discuss the topic more. And from the author's perspective, whether they are writing it to take advantage of the opportunity for increased page-views.
- mattgreenrocks 12y agoIt certainly happens. HN has a lot of self-promotion going on, and a lot of people love to hop on bandwagons. Both reasons are compelling evidence for consuming fewer blogs and more whitepapers; at least when it comes to the practice of developing software.
- gavinpc 12y ago> fewer blogs and more whitepapers Is there a Hacker News for whitepapers? Because I've heard this comment a few times now, and I'm ready to start.
- dukerutledge 12y agoSo look out for co, fibers, async, etc. posts in the coming days. Promises are still my flavor of choice for most use cases.
- cabbeer 12y agoIt's called content marketing.
- deleted 12y ago[deleted]
- tetha 12y agoI'm looking forward to this. I'm currently forced to deal with this strange world of promise based CSP-style development and I'm not sure if I like it or not, but it certainly is interesting. And I can certainly see the charm of such a solution, I can ignore that certain calls can block and everything stays responsive. Note that this is coming from someone who's usually fudging around somewhere deep in a server stack and who usually works on high-performance systems with careful control about threads, hot loops, boundaries between threads and such. Responsiveness isn't my world, but maybe I can steal some ideas here :)
- personZ 12y agoTopics do trend, and the various camps will quickly rush to author and promote things that conform with their worldview. Users will search for correlating content to submit. But to address something that is a personal peeve - "And from the author's perspective, whether they are writing it to take advantage of the opportunity for increased page-views." Much of the content that we see on here are people writing about topics that motivate them. If they saw a post that they think is wrong and they want to refute it, or if they think it is right and want to add supporting commentary, they author posts to support their position. The majority of these posts have no ads, which is good because it is catering to a market that overwhelmingly runs ad blockers. There is close to zero retention or residual value for audiences like HN: people click to your post, maybe read it (if that), and for the overwhelming majority that is the entirety of the relationship with the author. You don't shoot to the tops of the blogosphere. You don't rake in those fat Adsense dollars. You get a momentary period in the sun to evangelize some beliefs.
- city41 12y agoThis has happened at HN for as long as I can remember. I generally like it, as I like the added depth and new viewpoints this tends to bring. For what it's worth, I wrote this article on promises, but I didn't submit it today. I was surprised to see it show up here. So the trend is not always people trying to take advantage for their own benefit.
- rdtsc 12y agoOne reason is I think topics drop off too fast. I know there is a flame ramp-up algorithm or whatever it is called when a large number of comments is added. But I think that needs to be refined. If there a large number of longer and highly upvoted comment that thread should stay up higher. Say just recently there was an interesting thread comparing Erlang and Go concurrency and thread safety. There were interesting in-depth comments about schedulers and whatnot. Seemingly a good number of upvotes, yet before the end of the day the story was gone. So I think people do want to discuss things more and it needs to be fixed. Well I guess another way is to embrace this and just re-post other blogs and reactions and then in the thread post links to previous comments (as in "wait, you probably want to read the story from yesterday before commenting here..."), kind of idea.
- exogen 12y agoThe situation caused by promises gaining popularity and non-IE browsers refusing to implement setImmediate is really quite ugly. setTimeout's minimum value is defined to be 4ms by the HTML5 spec, so if the browser conforms to that and your app makes heavy use of promises (using setTimeout), now you're waiting multiple screen refreshes for updates – so you don't actually want to use setTimeout. Even though the asynchronous requirement is good for developers using the promise API, it really screwed over implementors. The setImmediate polyfills attempt a bunch of ugly fallbacks, including (depending on which one you use): yield/generators, MutationObserver, postMessage/MessageChannel, onreadystatechange, and finally setTimeout (the slowest). IMO the browser vendors should just give in and add setImmediate – if ever there was a need for it, this is it. But maybe they consider ES6 features a good enough substitute, I don't know.
- cpeterso 12y agoHere's the Firefox bug about implementing (or not) setImmediate: https://bugzilla.mozilla.org/show_bug.cgi?id=686201 https://bugzilla.mozilla.org/show_bug.cgi?id=686201
- lhorie 12y agoThis. Ran into this very issue when I was implementing promises in Mithril ( http://lhorie.github.io/mithril http://lhorie.github.io/mithril ). This really makes promise performance a much uglier beast than it needs to be. I took a less conventional road there: I deliberately violate the A+ spec and let surprises like the ones in the article example happen, in order to get good performance without hacks/bloat. Typically, promise resolution is usually done asynchronously anyways (otherwise, why bother using promises?), so this caveat would only be a problem in some serious case of misuse. In any case, surprises are fixable in application space (i.e. just move lines of code around), but performance degradation due to some deep implementation detail in the promise API / browsers not playing ball is nearly impossible to fix unless you switch to a non-conformant promise library (in which case, you'd have to fix the surprises anyways - assuming you had any cases of misuse to begin with).
- spion 12y ago
- malandrew 12y agoIf anyone reading this is very familiar with the Bluebird promises library, it would be awesome if you could write an in depth blog post on all the optimization strategies used by bluebird to minimize the memory and cpu overhead it achieves.
- spion 12y agoPetka Antonov (the author) wrote this: https://github.com/petkaantonov/bluebird/wiki/Optimization-killers https://github.com/petkaantonov/bluebird/wiki/Optimization-k... Other than that, I think he also said similar rules of C++ and Java optimization apply (avoid allocations a.k.a. creations of new objects, avoid avoidable work in special cases, take advantage of cache locality etc)
- dpweb 12y agoI'm not getting it. How is this? doSomething().then(function(result) { var results = [result]; results.push(88); return results; }).then(function(results) { results.push(99); return results; }).then(function(results) { console.log(results.join(', '); }); More attractive/readable and superior to this? function doSomething(pushEight); function pushEight(res){ res.push(88); pushNine(res); } function pushNine(res){ res.push(99); showResults(res); } function showResults(res){ console.log(res.join(', ')); } In addition to the anonymous functions I can't reuse elsewhere? Serious question, just asking..
- spion 12y agoHow about this slightly more realistic example? https://gist.github.com/spion/33b3bf013cc9181171b9#example https://gist.github.com/spion/33b3bf013cc9181171b9#example
- ufo 12y agoThe TL;DR: * Callbacks passed to cb-based libraries may be called twice - promises are only resolved once, either fulfilled or rejected. * Callback-based libraries may blow up if the callback throws - promise libraries shield the callback stack from "blowing up" (but do require slightly less careless management of resources at the call-stack site) * Callbacks passed to cb-based libraries may be called before the current even tick completes, potentially creating the zalgo problem - callbacks attached to promises are always called after the currently executed function finishes.
- ahoge 12y agoSee slides #19-#28: https://www.dartlang.org/slides/2013/06/dart-streams-are-the-future.pdf https://www.dartlang.org/slides/2013/06/dart-streams-are-the... It's Dart instead of JS, but the idea is pretty much the same.
- pornel 12y agoYour example is nice because: - Your functions are coupled and cooperate on shared mutable state (you can't pushNine and then pushTen). In large projects coupling like that starts to hurt a lot, so you need more isolated functions and store intermediate state somewhere - and closures are convenient for that, but don't nest too gracefully. - You don't have error handling. Promises don't make it bulletproof, but at least allow handling most errors in one place (so you don't need `if (err) return callback(err)` in every callback). But IMHO the `.then()` syntax is just a temporary solution. Promises become really awesomene with ES6 generators or ES7 async/await: async function doSomething(){ showResults([await getEight(), await getNine()]) }
- andrus 12y agoThe Promises/A+ assumption that you'd never want a Promise to return a Promise is really shortsighted.
- ephemeralgomi 12y agoI get a _lot_ of mileage out of being able to chain promises like that. If I really need to resolve a promise to a promise, I can resolve to an object wrapping the promise and then unwrap it on the receiving side.
- russellsprouts 12y agoPromises are really Monads for asynchronous results. A Monad kind of wraps a certain value. For example, we might have a Promise JSON from an API call. The bind method of a Monad (>>= in Haskell) takes a JSON Promise, and a function (JSON -> Promise b for some b), and returns a value of type Promise b. Promise.then is equivalent to bind. In Haskell you might define them like this: data Promise msg val = Resolve val | Reject msg deriving Show instance Monad (Promise msg) where return = Resolve (>>=) :: Promise msg val -> (val -> Promise msg b) -> Promise msg b (Reject msg) >>= _ = Reject msg (Resolve val) >>= f = f val They would be used like this newPromise = jsonPromise >>= transformJSON In JavaScript, you would write var newPromise = jsonPromise.then(transformJSON) However, the JavaScript case is slightly different. It is not as strict about types. It is possible (and typical) for transformJSON to return a bare type, rather than a Promise, while Haskell would require a Promise be returned every time. It treats an unwrapped value the same as an already fulfilled promise for that value. But automatically unboxing the promises that are returned gives them the full power of Monads.
- andrus 12y agoNo, "automatically unboxing the promises that are returned" does not give Promises "the full power of Monads", because you cannot represent a Promise for a Promise for a value. Promises/A+ breaks parametricity.
- iopq 12y agoPromises are an ad hoc, informally-specified, bug-ridden, slow implementation of half of a monad.
- KerrickStaley 12y agoIf a Promise is rejected, what happens to the return value of that Promise's .then() (assuming the onRejected handler doesn't throw)? Is it also rejected (as the article seems to suggest)? Or is it fulfilled (as the spec indicates, if I'm reading it correctly)?
- domenicd 12y agoIt's fulfilled. If you return from the rejection handler, instead of rethrowing, then you have handled the error: rejectedPromise.catch(e => { return 5; }); is similar to try { throwError(); } catch (e) { return 5; }
- gcr 12y agoWhoa. We've shifted from the (simpler) continuation-passing style with callbacks to this. Is this really worth it? Honestly, I don't think I like the whole idea of promises. What do we gain from this besides technical debt?
- mkoryak 12y agodo the words "callback hell" mean anything to you?
- zoomerang 12y agoCallbacks seem simpler in a lot of these examples because they aren't really showing the power of promises. Promises allow you to chain much more complex flows of information together in a way that would result in a mess of spaghetticode if attempted using callbacks.
- dsego 12y agoI suggest watching: Forbes Lindesay: Promises and Generators: control flow utopia -- JSConf EU 2013 https://www.youtube.com/watch?v=qbKWsbJ76-s https://www.youtube.com/watch?v=qbKWsbJ76-s
- tegeek 12y agoPromises are good solution to tackle call back problems. But once you spend a little time with Functional Reactive Programming, You never want to go back to any imperative solution. Functional Reactive Programming eliminates every scenario where you need a promise. FRP models "past, present & future" in a sense that you never need to use any "promises" library again. It brings such a higher level abstraction to your "time" dependent code, that you don't have to maintain state in your code. BaconJS is one of the simplest FRP library which brings simplicity & power to your JS projects. http://baconjs.github.io/ http://baconjs.github.io/
- spion 12y agoPromises aren't really imperative - they're just not suited to handling streams of events, only single values. Also, isn't suggesting FRP in place of promises like suggesting streams instead of callbacks, or arrays of values instead of values?
- domenicd 12y agoScalar variables are a good solution to tackle register problems. But once you spend a little time with Linked List Programming, You never want to go back to any scalar solution. Linked List Programming eliminates every scenario where you need a scalar. LLP models "beginning, middle & end" in a sense that you never need to use any "scalars" library again. It brings such a higher level abstraction to your "space" dependent code, that you don't have to maintain state in your code. JSClass's Linked List is one of the simplest LLP library which brings simplicity & power to your JS projects. http://jsclass.jcoglan.com/linkedlist.html http://jsclass.jcoglan.com/linkedlist.html
- auvrw 12y agoi'm at the beginning of a node project and need to choose a promises implementation. it seems like when and q are the most often cited, but then i've noticed someone mentioning this "bluebird" library. it seems like there are a ton of these things. any advice on which one to pick? does it really make a difference since they all conform to the A+ spec?