6 ms·
You have a number of ways of keeping a handle on async code now. 1. Native ES6 promises will cover most of your basic needs. See https://developer.mozilla.org/
by GeneralMaximus 10y ago
You have a number of ways of keeping a handle on async code now.
1. Native ES6 promises will cover most of your basic needs. See https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise https://developer.mozilla.org/en/docs/Web/JavaScript/Referen.... In fact, unless you have very specific needs not covered by native promises, you shouldn't drop a third party library into your project.
2. For more advanced operations on promises, use Bluebird. See http://bluebirdjs.com http://bluebirdjs.com and http://bluebirdjs.com/docs/api-reference.html http://bluebirdjs.com/docs/api-reference.html. It has a ton of features built on top of native ES6 promises. If you're using an older version of Node, it also acts as a polyfill. It can also make it easy to work with libraries that only expose a callback-based interface. So yeah, Bluebird is the shit.
3. co is a generator-based control flow library that can make your async code look more like synchronous code. It's pretty cool, but I haven't personally used it in a project, nor do I know of anyone else who uses it. It builds on top of promises and generators, and isn't very hard to understand under the hood. See https://github.com/tj/co https://github.com/tj/co. I wouldn't recommend it, but it might be something to play with because ...
4. ... async/await is coming to JavaScript! At a very high level, this pair of keywords is syntax sugar for what co already does as a library. This is the final stage in the evolution of taming callback hell in JavaScript, and it builds on top of everything that has come before (promises and generators). Here's a tutorial: https://blog.risingstack.com/async-await-node-js-7-nightly/ https://blog.risingstack.com/async-await-node-js-7-nightly/
- ykler 10y agoI am confused. Your recommendations 1 and 2 seem to conflict with one another. I use Bluebird now for promisification, and I also used a few other features including the resource management (disposers). Does this mean that I will be using Bluebird and not native promises for the foreseeable future? Or can/should I use Bluebird with native promises? (Or would that just make things slower if it is even possible?)
- GeneralMaximus 10y agoAutomatic promisification and the disposer pattern are both Bluebird-specific features that native ES6 promises don't support, so you'll have to continue using Bluebird if you rely on them. However, promises returned by Promises/A+ compliant libraries -- and this includes native ES6 promises -- are interoperable with each other. That means you can mix Bluebird promises with native promises for the most part. E.g, passing an ES6 promise to Bluebird's Promise.all will work just fine. This works up to a point, and breaks when you try to use a Bluebird-specific function that's expecting additional functionality to be attached to the promise object. I don't see why mixing Bluebird promises with ES6 promises would make anything slower. You shouldn't worry about this.
- SparkyMcUnicorn 10y agoBluebird is faster than native promises as well. http://softwareengineering.stackexchange.com/questions/278778/why-are-native-es6-promises-slower-and-more-memory-intensive-than-bluebird http://softwareengineering.stackexchange.com/questions/27877...
- gsathya_hn 10y agoNative promises and bluebird use different microtask queues on Node which makes interop incorrect (which is also one of the reasons why bluebird is ES6 spec non compliant). See https://gist.github.com/anonymous/9936c695f2c29e79a0c1a0dec863abea https://gist.github.com/anonymous/9936c695f2c29e79a0c1a0dec8... This might lead to subtle ordering bugs, I would recommend against using both together. Using bluebird and native promises together may result in slower performance because V8 has fast paths for native promises which fail for bluebird.
- randallsquared 10y agoIn what way is this incorrect? Those are three separate promises; no code can be correct that depends on whether one resolve() call finishes before an independently started resolve() call, right?
- Macha 10y agoIf the ordering is important, then you should be using a() .then(()=>b()) .then(()=>c()) Assuming anything about the completion order of: a(): b(); c(); Where a, b and c are async tasks of any kind (be they classic old callbacks, Promises, Observables, whatever) is just asking for trouble. The whole point is that you don't care about when it finishes, you just want to know that it has finished. If the order is that important and you don't want to handle managing it, you should just write standard synchronous code.
- nodesocket 10y agoAlso highly recommend the npm async library[1] even though the hipster way is now native async/wait or promises. caolan/async has some amazing sugar on nearly every use-case the most common for me being async.auto(). [1] https://github.com/caolan/async https://github.com/caolan/async
- Bahamut 10y agoI highly recommend against using that library - it encourages a lot of callback hell we've found at my company, and it is much harder to create nice reusable functions with it vs. promises. bluebird is a wholly superior library for handling async flow.
- zachrose 10y agoSo much of the promise-based code I see looks almost the same as it would with plain callbacks, just with the callbacks plopped into .then(). Am I missing something? How do promises make for more reusable functions?
- egeozcan 10y agoYou can take the part before `.then()` and pass it around.
- woudsma 10y agoyes that works quite great. you have to define a 'async' function, in which you can use the 'await' keyword. async getDoc(doc) { const result = await db.get(doc) console.log('result:', result) } // instead of: function getDoc(doc) { db.get(doc, result => { console.log('result:', result) }); } // or function getDoc(doc) { db.get(doc) .then(result => 'result: ' + result) .then(::console.log) .catch(::console.error) }
- latch 10y agoBecause promises are chainable, it can take N level-deep code down to 1 level deep. So that's your first big win. The second one is that you can await a promise, which turns your 1-level-deep code to 0 levels deep.
- grepthisab 10y agoMy understanding was that Node didn't support native ES6, is that no longer the case? Or are you talking about using a transpiler?
- Klathmon 10y agoNode supports all of ES2015 and ES2016 and will soon support ES2017 in the next few months or so. So yeah, for most things you don't need to use a transpiler.
- quarterto 10y agoNode has supported all of ES6 except modules since 6.0.
- grepthisab 10y agoAh, this explains it. I tried to use an import statement a couple days ago and it failed, so I assumed it still wasn't supporting ES6. Good to know!
- lojack 10y agoA year or two ago that was the case. Then io.js forked, implemented a bunch of features and later was brought back into the NodeJS fold. Since then, Node has been a lot more proactive about keeping up with newer specs.
- MehdiHK 10y agoYou can always check here: http://node.green http://node.green
- wereHamster 10y agoI don't see ES6 modules (import/export keywords etc) in that list. Where is that feature hiding?
- charrondev 10y ago
- devwastaken 10y agoPromises don't cover a lot of scenarios in async usage. When building some node apps, especially toolage, doing everything async just isn't possible, or is a lot more work for little benefit. The second you use a promise, anywhere, working with its output is now also async, you cannot 'wait' for it. I don't know if async/await actually does this or not, but until that functionality exists in JS, working with node, for me, is a pile of junk code, especially when libraries force you to use them asynchronously.
- AgentME 10y ago>working with its output is now also async, you cannot 'wait' for it ... , but until that functionality exists in JS, working with node, for me, is a pile of junk code, especially when libraries force you to use them asynchronously Asynchronicity is something that Node makes explicit and necessary for I/O, and it's practically a core principle of Node and javascript. If you try to avoid asynchronicity entirely, then you're not going to get much further than you would if you tried to avoid classes in Java. Async/await is a very useful syntax sugar to working with promises, but it's not built to let you ignore asynchronicity entirely.
- sfilargi 10y agoGrandparent: "lack of a definitive library" Parent: "You have a number of ways" Do you see the irony?
- jodoherty 10y agoI've used the `co` library at work to extensively trim down and simplify a lot of server-side Node.js code recently. It's worked out very well compared to the very Promise heavy code we had before, especially since so many database libraries now make use of promises. I would highly recommend it if you're going to be stuck using Node v6 for the next 2-4 years. On the front-end, we're using TypeScript 2.1.5, so we've been able to make good use of async/await there. The only tricky parts are dealing with AngularJS, due to the way it handles change detection via scope digests. Both solutions still require the use and understanding of ES6 promises, especially when dealing with code that only works with callbacks.