Skip to content

Backend: JavaScript and ES6

Tim K edited this page Sep 3, 2018 · 12 revisions

Fizzyo backend uses the "new" JavaScript

A lot of developers have previous experience writing JavaScript for browsers. Fizzyo-backend is completely different - it's running JavaScript as a backend platform, using Node.js.

Moreover, most developers are used to writing in an older flavour of JavaScript called EcmaScript 5, or ES5 for short. Fizzyo-backend, on the other hand, uses EcmaScript 6, or ES6. Take a look at the comparison below, where the same function called greetings is written in both ES5 and ES6.

// ES5 syntax --> Bad
function greetings (name) {
 return 'hello ' + name
}
// ES6 syntax --> Good
const greetings = (name) => {
 return `hello ${name}`;
}

As you can see, these code snippets look almost nothing alike, and that's because ES6 brings a lot of new features that make code much cleaner and more expressive. For general knowledge, I suggest you skim this article.

The more ES6 coding experience you can get, the better, so make sure to Google around and learn as much as you can. When in doubt, you can always look through the existing Fizzyo-backend code base and find some examples, or consult Tim Kuzhagaliyev.

Promises

Nearly all of the logic in Fizzyo web API and validator is async, and they heavily rely on so-called Promises. Promises can be hard to understand if you don't have much experience with async programming or JavaScript as a whole. Nevertheless, since they are used universally you must learn how to use them correctly. Here are two possible starting points:

  1. If you've used JavaScript before and know how JavaScript events work, you might want to read this article.
  2. If you just want to learn about promises, check out this page.

You'll need to read more to understand how promises work. "ES6 Promises in Depth" is a very good guide that will teach you all you need to know about promises (with nice animated diagrams), including how to create your own promises and how to convert callback-based functions into promises.

You should never write a function that takes a callback as an argument. In fact, if your function involves any sort of async operation (HTTP request, database query, writing file to disk) you should always return a promise. Other Fizzyo.

Keywords async and await were added in newer version of JavaScript (ES7+). Since we're targeting Node v8.x, you should not use these keywords to handle async operations - always use promises.

Docblocks

Docblocks are documentation comments that appear above methods and variables. They give hints to your IDE about what the types of different variables are, as well as useful information for developers. For example

/**
 * Creates a rectangle from the coordinates of the top left corner and dimensions.
 *
 * @param {{x: number, y:number}} corner Top left corner coordinates.
 * @param {number} width
 * @param {number} height
 * @returns {Box}
 */
createRectangle(corner, width, height) {
    const rightX = corner.x + width;
    // ... code
}

A smart IDE will figure the variable types based on the docblock, and warn me if I've accidentally passed in a string or a boolean instead of a number. Moreover, additional information in the docblock can help other developers figure out how your method must be called.

You are encouraged to add docblocks to all of the methods that you define.

Common mistakes

Here are some of the most common mistakes I've seen while reviewing JavaScript code for Fizzyo-backend:

  1. Using var keyword. var keyword is considered a bad practice now, you should either use const if the value is not going to change or let if you want to allow the value to change.
  2. Reassigning this, e.g.:
    let parent = this;
    // OR
    const that = this;
    With the new ES6 arrow functions, reassigning this is considered an anti-pattern. If you find yourself reassigning this, you're doing it wrong.
  3. Forgetting to return a promise. Promises are objects just like everything else in JavaScript, and the caller of your function will not be able to do anything with your promise unless you explicitly return it. Consider the two snippets below - it's a very subtle detail but it can make debugging very hard.
    doThis(value) {
        // Bad - forgot to return the promise
        Promise.resolve()
            .then(() => doThat(value));
    }
    doThis(value) {
        // Good - returned the promise
        return Promise.resolve()
            .then(() => doThat(value));
    }
  4. Using methods that are marked as ...Legacy() or @deprecated. You should never use legacy functions in new code - always check the function definition and see what you need to do. For example, this function tells you what exactly you need to use:
    /**
     * @deprecated Use `prepareAll()` and promises instead, See `V1UserRouter.db-spec.js#before()` for examples.
     * @param logger
     * @return {DBUtil}
     */
    static prepareLegacy(logger = bunyan.createLogger({name: 'fizzyo-test-db'})) {
        // ... code
    }

Pro-tips:

  1. Use an IDE or an editor with good code completion and static code checking, such as WebStorm or PhpStorm. They will catch most of your mistakes and tell you how to fix them, drastically increasing your efficiency.
  2. Don't use function myFunc(...) {} style definitions. With ES6, in 99.999% of the cases you can use an arrow function instead, i.e. const myFunc = (...) => {}.