ES2016 & ES2017

Reference

The next section of the class I’m doing builds on the ES2015 section and shows what’s new in ES2016 and ES2017.

For reference:

Exponentiation Operator

Now there is a shorthand way to calculate exponents:

//ES2015
var calculatedNumber = Math.pow(2,4);
calculatedNumber; // 16

//ES2016
var calculatedNumber = 2**4;
calculatedNumber; // 16

This also works with the equals = operator to accumulate exponents:

// ES2015
var nums = [1,2,3,4];
var total = 2;

for(let i = 0; i < nums.length; i++){
total = Math.pow(total,nums[i])
}

//ES2016
var nums = [1,2,3,4];
var total = 2;

for(let i = 0; i < nums.length; i++){
total **= nums[i];
}

Includes Method with Arrays

Now the includes() method is available to check for values in an array as well as strings:

// ES2015
var nums = [1,2,3,4,5];
nums.indexOf(3) > -1; // true
nums.indexOf(44) > -1; // false

// ES2016
var nums = [1,2,3,4,5];
nums.includes(3); // true
nums.includes(44); // false

padStart and padEnd

If you need to pad a string to be a specific length, these methods let you do it. The first parameter is the total desired length, and the second is the character to pad with (empty spaces if 2nd param is omitted):

"awesome".padStart(10); // "   awesome"
"awesome".padStart(10,'!'); // "!!!awesome"
"awesome".padEnd(10,'!'); // "awesome!!!"

Async Functions

Async functions simplify writing promises: with the await keyword (which can only be used inside async functions) you can pause the execution of the function to wait for a Promise to be resolved.

async function getMovieData(){
console.log("starting!");
var movieData = await $.getJSON('https://omdbapi.com?t=titanic&apikey=thewdb');
console.log("all done!"); // does NOT run until the promise is resolved!
console.log(movieData);
}

getMovieData()
// starting!
// Promise {<pending>}__proto__: Promise[[PromiseStatus]]: "resolved"[[PromiseValue]]: undefined
// all done!
// {Title: "Titanic", Year: "1997", Rated: "PG-13", Released: "19 Dec 1997", Runtime: "194 min", …}

Object & Class Async

Object methods can also get async function with the async keyword:

var movieCollector = {
data: "titanic",
async getMovie(){
var response = await $.getJSON(`https://omdbapi.com?t=${this.data}&apikey=thewdb`);
console.log(response);
}
}

movieCollector.getMovie();

Similarly, async functions can be included within a class constructor:

class MovieData {
constructor(name){
this.name = name;
}
async getMovie(){
var response = await $.getJSON(`https://omdbapi.com?t=${this.name}&apikey=thewdb`);
console.log(response);
}
}

var m = new MovieData('shrek');
m.getMovie();

Async Error Handling

To handle errors with async functions, you can use a try/catch statement:

async function getUser(user){
try {
var response = await $.getJSON(`https://api.github.com/users/${user}`);
console.log(response.name);
} catch(e){
console.log("User does not exist!");
}
}

getUser('elie'); // Elie Schoppik
getUser('foo!!!'); // User does not exist!

Sequential vs. Concurrent Async Requests

If you run multiple async requests within a function, each will wait in turn until the previous is resolved. In the example below responseTwo does not make the HTTP request until responseOne resolves:

async function getMovieData(){
var responseOne = await $.getJSON(`https://omdbapi.com?t=titanic&apikey=thewdb`);
var responseTwo = await $.getJSON(`https://omdbapi.com?t=shrek&apikey=thewdb`);
console.log(responseOne);
console.log(responseTwo);
}

This should be refactored to start the HTTP requests in parallel, and then await their resolved promises:

async function getMovieData(){
var titanicPromise = $.getJSON(`https://omdbapi.com?t=titanic&apikey=thewdb`);
var shrekPromise = $.getJSON(`https://omdbapi.com?t=shrek&apikey=thewdb`);

var titanicData = await titanicPromise;
var shrekData = await shrekPromise;

console.log(titanicData);
console.log(shrekData);
}

We can also use Promise.all() to await multiple resolved promises:

async function getMovieData(first, second){
var moviesList = await Promise.all([
$.getJSON(`https://omdbapi.com?t=${first}&apikey=thewdb`),
$.getJSON(`https://omdbapi.com?t=${second}&apikey=thewdb`)
]);
console.log(moviesList[0].Year);
console.log(moviesList[1].Year);
}

getMovieData('shrek', 'blade');

// 2001
// 1998

Object Rest & Spread

A proposed change in ES2017 is to introduce the rest & spread ... operator to objects. This would gather the rest of the keys and values in an object and create a new object out of them:

var instructor = {first:"Elie", last:"Schoppik", job:"Instructor", numSiblings:3};

var { first, last, ...data } = instructor
first; // "Elie"
last; // "Schoppik"
data; // { job: "Instructor", numSiblings: 3 }

You can also spread out keys and values to move them from one object to another:

var instructor = {first:"Elie", last:"Schoppik", job:"Instructor"};

var instructor2 = {...instructor, first:"Tim", last:"Garcia"};

The spread operator can also be used to assign default values more concisely than the Object.assign() method:

var defaults = {job: "Instructor", ownsCat:true, ownsDog: true};

var matt = {...defaults, ownsCat: false};

var colt = {...defaults, ownsDog: false};

Up Next

Next section we start on D3 and data visualizations!