Skip to content

Comment on ES6 in Depth: Destructuring

Comments

I'm currently building a rather large isomorphic React/Flux application in ES6 and ES7.

With our Flux implementation that we're using[0], async actions to external services become amazingly simple.

  async sendRequest(payload) {
      try {
          let result = await this.api.sendRequest(payload);
          return await result;
      } catch (e) {
          if (e.name === 'ServerException') {
              this.errorActions.serverError(e);
              return null;
          }
          
          this.errorActions.genericError(e);
          return null;
      }
  }
Having a class system on top of prototype system, removing a lot of the boilerplate is great. Browserify/CommonJS and Babel make for a phenomenal build system, and being able to with few exceptions render everything on the server correctly is brilliant.

Javascript has come a long way. The best part of destructuring is simplifying `import` statements

  import { fooFunc } from './Bar';
I highly recommend checking it out, as the confluence of ES6/7, Babel, React and Flux (with one way data-flow) feels like the future but here today. That, and I'm stoked that functional programming concepts are taking off!

[0] http://acdlite.github.io/flummox

Last time I checked, one problem with async (translated with regenerator by babel) was that transformed code is difficult to debug even with source maps. The stack traces are often useless and breakpoints map incorrectly. Also, since the async function is returning a Promise, you've to deal with Promise's own stack trace eating behavior.

To summarize, the code looks neat. But debugging a non-trivial app still has some way to go.

Just use asyncToGenerator in babel : "optional": ["asyncToGenerator"] http://babeljs.io/docs/advanced/transformers/other/async-to-...

It will transforms async functions to a generator, with a far better debugging experience, and generators are supported in chrome dev and firefox now.

I don't disagree, but one nice thing with babel is a plugin called babel-plugin-rewire; its a clone, if you will, of rewire -- a proxy for require calls that allows you to overwrite them.

With it, I can unit test my actions and other async modules in complete isolation, so the debugging burden is lessened. Id love to be able to remove console.trace() calls in my async code in the error handling side, and I think we will get there soon, but things can be worked around and the control flow becomes far easier to understand than using generators by hand, or callbacks.

control flow becomes far easier to understand than using generators by hand.

IMO, control flow has no advantages over generators. It is exactly the same thing, replace await with yield/yield-star. Btw, until aysnc debugging becomes better, replacing yield with delegating yield even gives you stack traces since the delegation is handled by the runtime (and control does not pass back to the function (like Q.async, co, spawn) that's driving generators).

  //From my current project
  static *getInitialProps(name) {
      var project = yield* Project.getByName(name);
      return { project };
  }

async is a better way to do things, I agree. In fact, I asked this silly question once on es-discuss and got educated. https://mail.mozilla.org/pipermail/es-discuss/2014-September...

Hey, I read that thread just the other week! Fascinating discussion, though I still disagree that generators have the control-flow advantage: while I personally don't see much of a difference, the other developers whom are newer to JS and asyc execution in general have found async/await conceptually simpler, despite the fact it's still compiled down to generators anyway.

You're right, in that it makes little difference in terms of semantics per se, but having implemented both in the application we're working on (which is at just under 10k semicolons, currently) async/await along with how Flummox/Flux implements the dispatcher, it allows you to work with async methods without propgating async through the entire call stack, and lets you think of the runtime as being synchronous-ish. I'm looking forward to finishing this project, as there's a tonne of stuff I want to write up about it; I think the big issue with ES6/7 is that there isn't a lot of "in the trenches" writeups.

Thanks so much for the discussion on esdiscuss by the way, it really helped me understand async execution and control flow in ES6/7.

PS. This is a neat project, HTTP servers with ES7 async/await. Similar in concept to Koa, but using the newer syntax! https://github.com/quinnjs/quinn

I really wanted people to figure out how to make prototype systems work for them but either the web browser isn't the best context for them or people are just too used to class-based systems. I looked at Self and it was neat but I haven't seen any larger or shorter-lived programs that take advantage of the prototype-based system.

Prototype-type based systems are cool in theory, but aren't much fun to use in practice. They are incredibly powerful and easy to abuse. Basically single inheritance in disguise.

Classes aren't great either, but at least using class inheritance makes you feel icky, you're not likely to have shared state on the prototype being randomly mutated, and it's pretty readable.

what would you recommend as the best "getting started" with Flux and/or Flummox? React is pretty damn simple to grasp but building apps with it and Flux has a steep curve.

Flummox's documentation is pretty great, so reading through it's guides and it's API documentation is what really made the concepts click for me. The best part of Flummox is that it abstracts away the dispatcher and the boilerplate that Facebook's Flux requires. It also is not singleton-based, which is a massive boon for rendering on the server.

The developer of Alt (http://alt.js.org), Josh, is currently working on some documentation that will be exactly what you're after -- head over to the Reactiflux community on Slack, and go check out Alt's GitHub as I believe it's being put up there!

EDIT: Oh, and I highly recommend going through this code: https://github.com/goatslacker/microflux -- it will really make how Flux works clear. Most "modern" (haha, Flux itself is what 12 months old?) Flux implementations are pretty simple to be honest, so their code is often the best place to look to see how things are supposed to work.

Happy to hear Babel is working well for you. I'm loving it too so far. Just to noet, named imports aren't technically destructuring though, since the syntax is different and doesn't nest. e.g.

    import { fooFunc as otherFooFunc} from './Bar';
not
    import { fooFunc: otherFooFunc} from './Bar';

Or ToffeeScript has been available for years and has a better syntax..

Classifying your code is something you might do when it's finished. But while most code bases are constantly changing, classes does not make any sense! They will just make it harder to re-factor the code, and you will end up with a bunch of unused code just because you decided to classify early on instead of just prototyping.

Import is another concept that will eventually make your code base unable to manage. You'll end up with imports everywhere, with a weird spaghetti, where it would be much better to use the modular pattern of breaking up the code in separate reusable modules.

As to classes, there are some places where they make sense, but for the most part, your code really represents workflows against objects (not necessarily classes) as your code/flow really doesn't care if it's a duck as long as it quack()'s.

As to the second part of your comment regarding imports... import really isn't any different than require, and in that vein is easy enough to reason against, and work through. For the most part, your discrete modules should be hierarchical in nature, and exposed as collections/wrappers via directory/index structures... this will make it easier to avoid spaghetti.

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.