JavaScript build tooling and the CLI

Something that’s come up recently in the front-end world is the topic of a learning curve and JavaScript tooling such and Webpack and Babel. While I agree that new tooling can sometimes be a pain to learn, since when did being a web developer/programmer/rockstar not require learning new things? I mean, learning the CLI is one thing, but it’s not suuuuper difficult and is definitely a skill that will serve you well in your career. On top of that, front-end build tooling has been around for a while, first with Grunt and then Gulp. Does Webpack make things that much more difficult?

The argument I’m making is partially around React and how Webpack (or similar) is required. To me, this doesn’t seem like a problem, as many languages require compilation during a build step. I see the build step and associated tooling a good thing, as it allows for more streamlined and complex programming concepts to be brought into front-end development.

If you’re worried about learning something like the Webpack build process, Create React App has got all the setup jank covered. In Vue, there’s vue-cli which similarly gets you set up. In both cases all it takes to get up and running is npm install then npm start. That’s not too bad!

I guess what I’m saying, if all this ‘new’ stuff bothers you as a developer, it might be time to 1.) upgrade your skills, or 2.) do something else. Things aren’t slowing down any time soon in the front-end landscape, better get on the wagon or jump off!

NodeJS Christmas trees and Promises

Lately, I’ve been getting more into NodeJS development and playing with various aspects of it. It’s a refreshing change from a mostly PHP oriented job and is uniquely challenging but familiar because of Javascript.

One of the early struggles I had with the framework was the concept of async code and callbacks. If you follow most of the tutorials and docs, you’re encouraged to write anonymous function based callbacks.

While this works for a simple application, when you start to scale, things get ugly – i.e. the Christmas Tree of hell:

Obviously, this way isn’t readable or maintainable. There’s also the issue of errors needed to be handled at each level of nesting. Not good and repetitive.

One of the oft-talked about solutions is Promises. Promises promised to be an easy solution. The concept of promises in async programming is talked about all over the internet, and I had a hard time understanding it at first. I eventually got the hang of it and tried to convert some code to use the Q module:

Great, looks good, relatively clean and it includes exception handling by default. Christmas tree is gone!

I did run into a few issues/shortcomings for me, that bothered me a bit.

First, most NPM modules don’t use promises internally, like mongoosejs. This is a problem since this now requires me the developer to inject promises into the callbacks (that’s what the Q.defer() is all about). While not a big deal, it’s a bit of an annoyance to start converting all my callbacks to use this syntax.

Additionally, I wasn’t able to successfully pass multiple arguments to successively linked functions. The docs for the Q module say you can nest promises to get multiple inputs in your closure, oh yay!

I see a Christmas tree appearing…

So after trying out promises, I came to a solution that worked in my situation. I stumbled across this blog post on NodeJS structure, Callback hell is a design choice. And suddenly, a lightbulb appeared.

You see, you don’t need to use anonymous functions as callbacks, you can pass in pre-defined functions. And with the handy-dandy bind() method available in ES5, you’re able to pass contextual variables to nest callbacks. Awesome.

Here’s what I finally came up with:

So you see, in the first method kickOffTwitterCall() I’m assigned things I want available to nest functions to ‘this’ reference. As long as each callback uses the .bind(this) I’ve got access to anything assigned to ‘this’.

There’s also the added benefit of being able to pass extra args to bind which will then be available in the callback:

I have no doubt promises have their place, and I intend to use them when possible, however in some situations, they’re just not the right fit. For me it was about code organization and readability, and bind() was able to accomplish what I needed. +1 for learning new things!