ES2017 introduced many new cool features, which we are going to see here.

String padding(padStart and padEnd)

We can now add some padding to our strings, either at the end (padEnd) or at the beginning (padStart) of them.

"hello".padStart(6);
// " hello"
"hello".padEnd(6);
// "hello "

We specified that we want 6 as our padding, but why in both cases we got only 1 space?
It happens because padStart and padEnd will go and fill the empty spaces. In our example “hello” is 5 letters, and our padding is 6, which leaves only 1 empty space.

Look at this example:

"hi".padStart(10);
// 10 - 2 = 8 empty spaces
// "        hi"
"welcome".padStart(10);
// 10 - 6 = 4 empty spaces
// "   welcome"

 

Right align with padStart

We can use padStart if we want to right align something.

const strings = ["short", "medium length", "very long string"];

const longestString = strings.sort(str => str.length)
                              .map(str => str.length)[0];

strings.forEach(str => console.log(str.padStart(longestString)));

// very long string
//    medium length
//            short

First we grabbed the longest of our strings and measured its length. We then applied a padStart to all the strings based on the length of the longest so that we now have all of them perfectly aligned to the right.

 

Add a custom value to the padding

We are not bound to just add a white space as a padding, we can pass both strings and numbers.

"hello".padEnd(13," Alberto");
// "hello Alberto"
"1".padStart(3,0);
// "001"
"99".padStart(3,0);
// "099"

 

Object.entries() and Object.values()

Let’s first create an Object.

const family = {
  father: "Jonathan Kent",
  mother: "Martha Kent",
  son: "Clark Kent",
}

In previous versions of JavaScript we would have accessed the values inside the object like this:

Object.keys(family);
// ["father", "mother", "son"]
family.father;
"Jonathan Kent"

Object.keys() returned us only the keys of the object that we then had to use to access the values.

We now have two more ways of accessing our objects:

Object.values(family);
// ["Jonathan Kent", "Martha Kent", "Clark Kent"]

Object.entries(family);
// ["father", "Jonathan Kent"]
// ["mother", "Martha Kent"]
// ["son", "Clark Kent"]

Object.values() returns an array of all the values whilst Object.entries() returns an array of arrays containing both keys and values.

 

Object.getOwnPropertyDescriptors()

This method will return all the own property descriptors of an object.
The attributes it can return are value, writable, get, set, configurable and enumerable.

const myObj = {
  name: "Alberto",
  age: 25,
  greet() {
    console.log("hello");
  },
}
Object.getOwnPropertyDescriptors(myObj);
// age:{value: 25, writable: true, enumerable: true, configurable: true}

// greet:{value: ƒ, writable: true, enumerable: true, configurable: true}

// name:{value: "Alberto", writable: true, enumerable: true, configurable: true}

 

Trailing commas in function parameter lists and calls

This is just a minor change to a syntax. Now, when writing objects we need to leave a trailing comma after each parameter, whether or not it is the last one.

// from this
const object = {
  prop1: "prop",
  prop2: "propop"
}

// to this
const object = {
  prop1: "prop",
  prop2: "propop",
}

Notice how I wrote a comma at the end of the second property.
It will not throw any error if you don’t put it, but it’s a better practice to follow as it will make the life easier to your colleague or team members.

// I write
const object = {
  prop1: "prop",
  prop2: "propop"
}

// my colleague updates the code, adding a new property
const object = {
  prop1: "prop",
  prop2: "propop"
  prop3: "propopop"
}
// suddenly, he gets an error because he did not notice that I forgot to leave a comma at the end of the last parameter.

 

Shared memory and Atomics

From MDN:

When memory is shared, multiple threads can read and write the same data in memory. Atomic operations make sure that predictable values are written and read, that operations are finished before the next operation starts and that operations are not interrupted.

Atomics is not a constructor, all of its properties and methods are static (just like Math) therefore we cannot use it with a new operator or invoke the Atomics object as a function.

Examples of its methods are:

  • add / sub
  • and / or / xor
  • load / store

 

Async and Await

ES2017 introduced a new way of working with promises, called “async/await”.

 

Promise review

Before we dive in this new syntax let’s quickly review how we would usually write a promise:

// fetch a user from github
fetch('api.github.com/user/AlbertoMontalesi').then( res => {
  // return the data in json format
  return res.json();
}).then(res => {
  // if everything went well, print the data
  console.log(res);
}).catch( err => {
  // or print the error
  console.log(err);
})

This is a very simple promise to fetch a user from GitHub and print it to the console.

Let’s see a different example:

function walk(amount) {
  return new Promise((resolve,reject) => {
    if (amount < 500) {
      reject ("the value is too small");
    }
    setTimeout(() => resolve(`you walked for ${amount}ms`),amount);
  });
}

walk(1000).then(res => {
  console.log(res);
  return walk(500);
}).then(res => {
  console.log(res);
  return walk(700);
}).then(res => {
  console.log(res);
  return walk(800);
}).then(res => {
  console.log(res);
  return walk(100);
}).then(res => {
  console.log(res);
  return walk(400);
}).then(res => {
  console.log(res);
  return walk(600);
});

// you walked for 1000ms
// you walked for 500ms 
// you walked for 700ms 
// you walked for 800ms 
// uncaught exception: the value is too small

Let’s see how we can rewrite this Promise with the new async/await syntax.

 

Async and Await

function walk(amount) {
  return new Promise((resolve,reject) => {
    if (amount < 500) {
      reject ("the value is too small");
    }
    setTimeout(() => resolve(`you walked for ${amount}ms`),amount);
  });
}

// create an async function
async function go() {
  // use the keyword `await` to wait for the response
  const res = await walk(500);
  console.log(res);
  const res2 = await walk(900);
  console.log(res2);
  const res3 = await walk(600);
  console.log(res3);
  const res4 = await walk(700);
  console.log(res4);
  const res5 = await walk(400);
  console.log(res5);
  console.log("finished");
}

go();

// you walked for 500ms 
// you walked for 900ms 
// you walked for 600ms 
// you walked for 700ms 
// uncaught exception: the value is too small

Let’s break down what we just did:

  • to create an async function we need to put the async keyword in front of it
  • the keyword will tell JavaScript to always return a promise
  • if we specify to return <non-promise> it will return a value wrapped inside a promise
  • the await keyword only works inside an async function.
  • as the name implies, await will tell JavaScript to wait until the promise returns its result

Let’s see what happens if we try to use await outside an async function

// use await inside a normal function
function func() {
  let promise = Promise.resolve(1);
  let result = await promise; 
}
func();
// SyntaxError: await is only valid in async functions and async generators


// use await in the top-level code
let response = Promise.resolve("hi");
let result = await response;
// SyntaxError: await is only valid in async functions and async generators

Remember that you can only use await inside an async function.

 

Error handling

In a normal promise we would use .catch() to catch eventual errors returned by the promise.
Here, it is not much different:

async function asyncFunc() {

  try {
    let response = await fetch('http:your-url');
    } catch(err) {
        console.log(err);
      }
}

asyncFunc();
// TypeError: failed to fetch

We use try...catch to grab the error, but in a case where we do not have them we can still catch the error like this:

async function asyncFunc(){
  let response = await fetch('http:your-url');
}
asyncFunc();
// Uncaught (in promise) TypeError: Failed to fetch

asyncFunc().catch(console.log);
// TypeError: Failed to fetch

Spread the love
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

Leave a Reply

%d bloggers like this: