True, there's a plethora of JS tools someone can use. The problem is that they have to be discovered. And there's no standard. I found out about Browserify 2 days ago and realised all the problems it could have solved for me. Now I have to migrate the code I have to it.
Utilities should be a part of the language's "battery".
Ambiguous/Unexpected behaviour: I mean I can redirect you to the popular "Wat" talk. Moreover, isn't that the entire premise of "Javascript: The Good Parts" anyway?
Flow isn't mature enough yet, but even TypeScript eliminates pretty much the entire Wat talk.
Also, it compiles to CommonJS, which means it works well with both node and browserify.
Yes, we need a blessed, "batteries included" stack for JS made of components that play nicely together. Here is a nice list to get started with (IMO, ymmv)
1. TypeScript or Flow
2. React
3. Promises: bluebird, when or p-promise
4. Observables: rxjs or most (they play well with promises)
5. immutable-js for immutable data structures
6. lodash and/or Ramda.js
7. browserify
1. Not a problem, though I don't use either, I tend to use very small modules (not necessarily via npm, but require'd in my own project, or outside modules)
2. React, and even the Yahoo flux tools are pretty nice. React by itself is less useful.
3. I'd go with es6-promise here, which complies with the spec. I wrote i-promise as a module to give an ES6 compatible promise library, or native as available.
4. Observables are pretty evil... the whole flux architecture is to avoid direct observations in favor of a unidirectional data flow.. but that's more opinion.
5. completely agreed... immutable data flows work to prevent side effects. Even if you don't use these libraries, avoiding side effects is a big thing.
6. Also agreed, though you can usually get the parts you want without the weird deep dependency chains in lodash.
7. Agreed here, though webpack is interesting, imho it breaks too much with node's approach to includes, and doesn't work as well with reusing code on the server-side (imho).
Other things to look into include csp, streams, events and the gulp build tool.
Well, observables would just be used as a mechanism to implement a flux-like architecture or decouple various parts of your server-side codebase (making them open to extension). A bit like event emitters, but without the stringly typed event names. I don't think thats evil? [1]
Or they can also be used in place of asynchronous lists (like "object streams"). I find them handy for various tasks :)
Regarding es6-promise, its too minimal for my taste, and missing my favorite feature (provided by bluebird. when and p-promise): long stack traces on (possibly) unhandled errors, which are quite invaluable on the server side when debugging longer chains of events. p-promise has the additional advantage of being a relatively small library which is pretty awesome :)
I also agree with just about everything here, and thanks for the tip on es6-promise. I'll have to check it out.
I actually have this entire stack running without observables currently, and my goal is to build a variety of applications using it to really sort out the best techniques with it, and then open source it as a platform.
As for #7. I use webpack and love it. It does work wonderfully server side as well, you just have a build step with webpack that strips out anything you don't want for the server, and then have your server run that built file. Not perfect, but works well. It also avoids any need for gulp.
If you're already at the point where you are utilizing compilation, why not implement a compiler-level async/await solution (probably based off of a loop + a state machine, a la regenerator).
Even with generators we still need to yield something or await on something. C# awaits on Tasks, in JS Promises would be a logical choice. You definitely need a value though - you can't await for node style callback functions as they provide no value to yield (or otherwise pass to the runtime) between calling the function with a callback and your callback getting called.
Even so, lambdas, observables and some FP constructs such as map/reduce/filter/etc can potentially eliminate the need for imperative style code. There are also some semi-imperative solutions to certain problems that work okay [1]
Another advantage of functional code is that its easy to extend - adding a combinator that implements filtered (typed) catch for promises is a lot easier than implementing a language construct such as `catch (e if e.code == 404)` for generators.
var only = (predicate, handler) => e => {
if (predicate(e)) return handler(e) else throw e;
}
promise.catch(only(e => e.code == 404, e => {
handle...
}))
Here is another example (its a bit of an overkill though :)
JS ecosystem is confusing. See: https://news.ycombinator.com/item?id=7074307
Utilities should be a part of the language's "battery".
Ambiguous/Unexpected behaviour: I mean I can redirect you to the popular "Wat" talk. Moreover, isn't that the entire premise of "Javascript: The Good Parts" anyway?