The whole promisify is a good example of general node.js culture. It's considered "good enough" and everyone just uses it. However, anyone who has done software development in more solid languages would feel very uneasy using something like this. It's not really the fault of the JS developers, the dynamic nature of the language offers no other choice. For example, when Java added lambdas, since it has static typing it could consider a certain type of class (a single method class) as automatically a lambda. This allowed full backwards compatibility with any old library that conformed to this (and many libraries such as Guava did use single method class as a kind of "ugly" lambda).
node.js has a convention for callbacks (function(err, result)), but unfortunately it's only a convention and there's no compiler to enforce it. So automatic promisification is not possible. That leads to the current situation. There's all these new language features in JS, but everyone is still sticking to the "lowest common denominator" of callbacks. There's no path forward for existing libraries. The only way is a complete rewrite of libraries using the new Promise/async/await style.
Maybe we can all agree that experience in other languages leaves ECMAScript with much to be desired. Whether the changes ES6 hath wrought and ES7 and friends portend bode ill or well is likewise up for debate. So are the one-trueness of futures, specialized async syntax, and static typing. Those aren't either-or kinds of debates as far as ECMAScript is concerned. ECMAScript could be more Scheme-like, more Java-like, more ML-like. I've forgotten to mention some other disappointed camp. Forgive me!
If specific judgments on those kinds of controversies unify a culture, there is no unified culture of Node.js, any more than there is a unified culture of C or Java or English punctuation. The only unity is that standards-compliant ECMAScript runtimes are everywhere and we all want to use them. As long as different tastes are at least sufficiently well specified, we've a fighting chance of automating adapters. So I'd argue promisifiers and depromisifiers might be the most important libraries of the moment, culturally speaking. But it's too much to ask of any broad and adaptable common platform or library to hide the fact that tastes and approaches differ.
Thats also one cool thing of the js/node community. We just adopt stuff and try it out. With microservices, this also poses no problem. If it doesn't work, do it differently in the next service.
[1] I know, I know. A+ Promises are violating some laws BUT the general idea holds. And there are full monadic promise libraries like Data.Task or Fluture available.
If you want promises, just embrace promisify. I get a lot of this fear about error-first callbacks being only a "convention", but everything follows this convention in practice. Anything that can't be promisified because of that will likely have a pull request or a more popular fork that can.
I don't think node core libraries should be promise-based, and you can't expect the whole ecosystem to switch to promises if node core won't. At some point you have to jump to callback-style to live on node.
I also don't really understand what this post has to do with the release.
I don't see how compile-time type checking would help here. When checking out a new library, I read the documentation, or maybe it's test suite, and then use it accordingly. My tests ensure that I use it correctly, i.e. give it types it understands, give it the right data (the id of the correct user account for example), and handle the outcome correctly (i.e. display it in the right format).
JavaScript has run-time type checking, which could be used for automatic promisification, but I agree that's a slippery road, for many reasons.
Also you slipped in weasel language to disrespect JS developers. I have been coding for 30 years in wverything from assembly to C++ to C# to OCaml to now for the last several years mainly Node.js. Your comment was (reading between the lines) as close as you could get on Hacker News to spitting in my face.
Promisifying works fine. So do rewrites, as the language has evolved rapidly.
We do not actually have a big backwards compatibility problem.
Dynamic languages are dynamic.
We need something like promises to replace node streams too. We need streams with well defined semantics. Quick, what are the unpipe semantics for stream erors? Does a stream unpipe from its source? Will it unpipe synchronously or asynchronously? Can a stream emit an error synchronously when its created? At the next tick of the event loop? What about at the end of the same tick? Are these semantics defined anywhere? Which versions of node streams adhere to them? All is fuzzy.
We need to replace node streams and of all eventemitter-based streamlike stuff, badly.
Regarding types, you always have the option to add TypeScript into the mix.
It's all good for prototyping, but man, once you're up in production, dynamism is a recipe for pain. Granted, statically typed languages crash too, but the big difference is that you can often eliminate the same problem throughout your program by getting the type right, as opposed to trying to TDD bugs one at a time as they emerge.
I think you nailed it when you said, "there's no compiler to enforce it". Actually, maybe a compiler isn't the key word, but automated checks is the idea. A type-checking compiler is just one solution, albeit a pretty powerful one. Type inference makes it much less onerous these days. But even staunch dynamic language devs have come around to embrace the use of linters. So while it's often seemed that static and dynamic language users would always be at odds, perhaps a convergence is slowly happening.
The sounds like a limitation of promisify, not inherently of callbacks. There are many situations and styles where callbacks are perfectly adequate, and promises offer no benefit, so referring to it as the "old callback style" may be a bit premature.
Promises are superior in general, I guess that has been discussed already[1], many times. Promises may indeed offer just an insignificant benefit sometimes (you can even call it just a different style), for example when you are first writing a monolithic prototype. In this worst case, you would simply make a giant chain of ".then" methods, any your gain is you can get creative with the error handling if you want. However, the greatest benefit revels itself later: The composability that comes with them will help you immensely when refactoring.
[1]: One example: http://softwareengineering.stackexchange.com/a/302456/9451 Another: http://blog.parse.com/learn/engineering/whats-so-great-about...
You're just saying that if you make a mistake and use it wrong it doesn't work. That applies to all code, not just promisify.
> Also, the library writers are not writing the code with any guarantees that promisify will always work. So even if it works now, it could break in the future.
That also applies to all code, not just promisify. If the author changes their API without a major version bump, that can break any code that relied on the old API.
Promisify is deterministic and works as specified, 100% of the time. If it doesn't work, that means you passed a function with the wrong signature.
To my understanding, the following code examples do the same thing:
readFilePromise("file").then(... txt ...);
txt = readFileSync("file");
txt = await readFilePromise("file");
Why not use the one in the middle ?In a simple script you run from your shell, the middle one is fine.
Use $q.when() in your code if you aren't sure you're getting a promise.
Kind of wish there was yet another number prefix to semver to signify this.
The line of "major" is arbitrary, and changes per person. It's basically useless information to everyone but the person/people actually making the version change. Having it there can just lead to anger when something that you would consider "major" doesn't make the cut, or when the "major" bump doesn't have anything you care about.
Semver is in no way the end-all-be-all of versioning schemes, but at least it's pretty objective for the most part in the sense that it can prevent bikeshedding about version numbers, while still giving some useful information to the users.
That being said, I'd love a system that lets me view changelogs by the version "level" I want. So I can easily lookup the major changes since v6.6, and someone else can check what has change since v4.2, etc... With Semver a lot of my time is spent reviewing every changelog between my current version and the one i'm bumping to, and there's no reason it needs to be that way.
If I release 1.0, then add a couple "medium" size features and release as 1.1 a month or so later, I can keep doing this indefinitely with 1.2, 1.3, etc. Baring some truly some new big thing or a fundamental change in functionality, it becomes very unclear as to when to release "2.0" or what even makes it different than the other 1.x releases.
On the other hand, if I do the exact same work of adding a couple features per month, but don't actually release, I could then make a big splash a year later with 2.0 that had 19 new features, and I think most people could readily agree that qualifies as a "major" release.
From a quality point of view, release early, release often is very useful: get feedback quickly, iterate in small chunks, minimize breakage.
However, from a marketing point of view, this is boring -- especially by the time you're on 1.19 and your features are largely quality-of-life or only affect a small segment of the market. A big 2.0 release that gets press releases and such is much more exciting.
For software, I would apply the rule as such: 1) merge the major and minor segments, and the revision segment becomes equivalent, 2) then you follow the Form, Fit or Function rule and apply it to the core product, programs, and APIs.
[0] http://www.arenasolutions.com/resources/articles/form-fit-fu...
[1] http://www.buyplm.com/plm-good-practice/plm-software-part-re...
Our MIS vendor offers this, and it's indispensable. Especially considering that each of their customers are on a different version at any given time. You select your current version, and any other version to compare it to, and it spits out a report of all the differences from the module level down to the object attribute level, all nicely separated into logical groups. Due to the complexity of the system, I couldn't imagine a successful upgrade without it.
> I'm glad to hear so much excitement about async/await. However, Node v7 is based on V8 54, whose async/await implementation has some bugs in it (including a nasty memory leak). I would not recommend using --harmony-async-await in production until upgrading to V8 55
source: https://github.com/nodejs/promises/issues/4#issuecomment-254...
With semver, it seems like a lot of "new features" are typically released in minor versions, since quite often they don't need to break compatibility in order to introduce features. So major versions are, to me, almost more of a cause for concern these days. My first thought is typically "Oh no, what part of my stack is going to break now? How much time will I spend tracking down the fix?"
The LTS versions are named after the periodic table of elements, starting at a and moving forward. First one was "Argon" (4.x), second "Boron" (6.x).
You can read more on LTS and naming here: https://github.com/nodejs/LTS
Node.js V7
Node.js V8! (denotes something significant)
It's in the works and slated for a later release, but makes it such that yarn is not a universally viable replacement for npm yet.
> there is no yarn equivalent to "npm run ..."
https://yarnpkg.com/en/docs/cli/run ? (I am not primarily a node dev, so I might be missing some nuance here.)- await/async behind flag (already covered in thread)
- Exponentiation operator:
> console.log(60**2*24);
86400
- Object.{values,entries}: > o = { a: 1, b: 2}
> Object.values(o);
[ 1, 2 ]
- Object.getOwnPropertyDescriptor(s): > o = { a: 1 }
> Object.getOwnPropertyDescriptors(o);
{ a: { value: 1, writable: true, enumerable: true, configurable: true } }
Additionally, there's a lot of pretty impressive optimization work done by the v8 team. You can read more about that on their blog: http://v8project.blogspot.comFinally, one of my favorite things about Node.js 7.0 is the WhatWG http parser: https://github.com/nodejs/node/pull/7448.
edit: elaborated on exponentiation operator
Joking aside, I wonder if there are any internal plans on keeping terminology clear for the next version?