Friday, December 30, 2016

JavaScript Evolution ESMAScript 6 - Promises

Typically, to avoid blocking the main thread of execution, we write non-blocking code using asynchronous style function pass callback like this:
getResult("Saas", function(result) {
  ui.renderSidebar(results);
}
When nested callbacks start to grow, our code becomes harder to read. We have to check for error on every callback.
getResultFromServer("Saas", function(error, results) {
  if (error) { // handle error };
  ui.renderSideBar(results, function(error, results) {
    if (error) { //handle error };
    sendNotificationToServer(results, function(error, response) {
      if (error) { // handle error };
      doSomethingElse (response, function(error)) {
        if (error) { //handle error };
        //...
      };
    };
  };
});
Promises brought to JavasScript trying to offer a solution to this issue by bringing new abstraction that allows us to write asynchronous code in an easier way.
getResultFromServer("Saas")
  .then(ui.renderSidebar)
  .then(sendNotificationToServer)
  .then(doSomethingElse)
  .catch(function(error) {
    console.log("Error :" + error);
  }
The Promise constructor function takes an anonymous function with 2 callback argument known as handles. Handles are responsible for resolving or rejecting the Promise.

Create a new Promise automatically set it to the pending state. Then, it can become fulfilled(resolve) or rejected(reject).

One thing to remember is that Promise not return a result, its return a future value, such as the eventual result if asynchronous operation.

Let's wrap the XMLHttpRequest object API within a Promise. Calling the resolve() handler moves the Promise to a fulfilled state. We'll call the reject() handler for unsuccessful status codes and also when the error event is triggered on our request object. Both move the Promise to a rejected state.
function getResultFromServer(pollName){
  return new Promise(function(resolve, reject) {
    request.onload = function() {
      if (request.status >= 200 && request.status < 400) {
        resolve(request.response);
      } else {
        reject(new Error(request,status));
      };
    };
    request.oneerror = function() {
      reject(new Error ("Error Fetching Results"));
    };
  };
};
We can use then() method to read results from the Promise once resolved. We can chain multiple calls to then(). The return value from 1 call is passed as an argument to the next.

Once an error occurs, execution moves immediately to the catch() function. None of the remaining then() function are invoked.
getResultFromServer("Saas")
  .then(function(result){
    // Return value to next then().
    return result.filter((result) => result.city === "Orlado");
  })
  .then(function(resultFromOrlando){
    ui.renderSideBar(resultsFromOrlando);
  })
  .catch(function(error) {
    console.log("Error : " + error);
  })

Friday, December 23, 2016

JavaScript Evolution ESMAScript 6 - Module

In this section, we learn about using Module to encapsulate classes.

To export classes, use the export syntax with the class name inside curly braces.

flash-message.js
class FlashMessage {

  constructor(message) {
    this.message = message;
  }

  renderAlert() {
    alert(`${this.message} from alert`);
  }

  renderConsole() {
    console.log(`${this.message} from log`);
  }

}

export {FlashMessage} // Export class to outside world.
To import the class, we must use the same export name.

app.js
import {FlashMessage} from './flash-message';

let flash = new FlashMessage('Hello');
flash.renderAlert(); // Alert -> Hello from alert
flash.renderConsole(); // Console -> Hello from log

JavaScript Evolution ESMAScript 6 - Classes

A common encapsulation approach in JavaScript is using construction function. Adding the prototype required a bit of coding and some repetition. We can do better using new Class syntax to write the object-oriented language.

To define a class, we use class syntax followed by the name of the class. The body of a class is the part between curly braces.

Currently, there is no access modifier in JavaScript, like private and protected in another language. Prefixing a method with an underscore is a convention for indicating that it shouldn't be invoked from public API.
class SponsorWidget {
  // Constructor method is a special method for creating and initializing an object.
  // Its run every time a new instance is created with the new operator.
  constructor(name, description, url) {
    this.name = name;
    this.description = description;
    this.url = url;
  }

  // Private method
  _buildURL(url) {
    console.log(url);
  }

  // Instance method definition in classes look just like the method initializer shorthand in object.
  render() {
    // Variable set in constructor can be accessed from all other instance method using this. syntax.
    let link = this._buildURL(this.url);
  }
}

// Here is how we involve the class
let sponsorWidget = new SponsorWidget(
  "Google",
  "Search",
  "https://www.google.com"
);

sponsorWidget.render();

One benefit of class syntax is that we can use class inheritance. The extends syntax is used to create a class that inherit methods and properties from another class. The super method runs the constructor function from the parent class.
// Parent Class
class Widget {
  constructor() {
    this.baseCSS = "site-widget";
  }

  parse(value) {
    console.log(this.baseCSS);
  }
}

// Child Class
class SponsorWidget extends Widget {
  constructor(name, description, url) {
    super(); // Run parent constructor.
    this.name = name;
    this.description = description;
    this.url = url;
  }

  _buildURL(url) {
    console.log(url);
  }

  render() {
    let link = this._buildURL(this.url);

    // Calling inherit property and method
    this.parse(this.baseCSS);
  }
}
You can override the inherited method by naming the same method name in child class.
// Parent Class
class Widget {
  constructor() {
    this.baseCSS = "site-widget";
  }

  parse(value) {
    return this.baseCSS;
  }
}

// Child Class
class SponsorWidget extends Widget {
  constructor(name, description, url) {
    super(); // Run parent constructor.
    this.name = name;
    this.description = description;
    this.url = url;
  }

  _buildURL(url) {
    console.log(url);
  }

  // Overriding inherit method
  parse(value) {
    // Using super to call parent method
    console.log("Overring method: " + super.parse(this.name));
  }

  render() {
    let link = this._buildURL(this.url);

    // Calling inherit property and method
    this.parse(this.baseCSS);
  }
}

Thursday, December 22, 2016

JavaScript Evolution ECMAScript 6 - Sets

Before we understand the needs to use Sets, let's go back to understand Array limitation.

Array in JavaScript is very simple to use, but 1 thing they don't do is Array doesn't enforce uniqueness of items. Duplicate entries are allowed.
let tags = [];
tags.push ("JavaScript");
tags.push("Programming");
tags.push("Web");
tags.push("Web");

console.log(tags.length); // Return 4
If we want to prevent duplicate entry to be added into a collection, instead of Array, we can use Set. Set object stores uniques values of any types, where primitives values or object references.
let tags = new Set();
tags.add("JavaScript");
tags.add("Programming");
tags.add({version: "2015"}); // We can add object
tags.add("Web");
tags.add("Web"); // Duplicate entry are ignored.

console.log(tags.size); // Return 4
Set object is iterative, which means they can be used with for...of and destructuring.
for (let tag of tags) {
  console.log(tag);
}

// Return:
// JavaScript
// Programming
// {version: "2015"}
// Web

let [a, b,c, d] = tags;
console.log(a ,b, c, d);

// Return JavaScript, Programming, {version: "2015"}, Web

JavaScript Evolution ECMAScript 6 - WeakMap (Better with Memory with Limitation)

WeakMap is a type of Map where only Objects can be passed as keys. Primitive data types such as String, Number, Boolean, etc are not allowed.
let user = {};
let comment = {};

let mapSettings = new WeakMap();
mapSettings.set(user, "Sam");
mapSettings.set(comment, "Great Post!!!");

console.log(mapSettings.get(user)); // Return Sam
console.log(mapSettings.get(comment)); // Return Great Post!!!
You can't assign primitive data types as key.
let mapSettings = new WeakMap();
mapSettings.set("user", "Sam"); // Return Error - Invalid value used as weak map key
Other methods available are has() and delete().
console.log(mapSettings.has(user)); // Return true
console.log(mapSettings.delete(user)); // Return true
WeakMap is not iterable, therefore they can't be used with for...of.

JavaScript Evolution ECMAScript 6 - Maps

Maps are a data structure composed of a collection of key/value pairs. they are very useful to store simple data such as property value. They are present in many programming languages such a Scala.

The key in Map must be unique and associated with only 1 value.

key ---> value
key ---> value
key ---> value

JavaScript developer explores to Map thru Object. It is possible to use Object as Map, but there is some issue with that. The biggest issue of using Object as Map is the key always converted to String.

Let's take a look at the below example:
let user1 = {name: "Sam"};
let user2 = {name: "Tyler"};

let totalReplies = {};
totalReplies [user1] = 5;
totalReplies [user2] = 42;

console.log(totalReplies [user1]); // Return 42
console.log(totalReplies [user2]); // Return 42
Although we assign 2 different value to the key, the last assign overwrites the previous value because JavaScript converts the Object to String - [object, object].

To get around this issue, we should use the Map. Any value may be used as either a key or a value are not converted to String. Let change totalReplied to a Map.
let user1 = {name: "Sam"};
let user2 = {name: "Tyler"};

let totalReplies = new Map();
totalReplies.set(user1, 5);
totalReplies.set(user2, 42);

console.log(totalReplies.get(user1)); // Return 5
console.log(totalReplies.get(user2)); // Return 42
As you can see, the 2 value assigned to different Object key as expected.

We use get() and set() methods to access the value in Map. To delete a value in Map, you can use delete() method.
totalReplies.delete(user1);
The map is iteratable, so they can be used in the for...of loop. Each ran of the loop returns a [key, value] pair for an entry in the Map.
let mapSettings = new Map();
mapSettings.set("user", "Sam");
mapSettings.set("topic", "ES2015");

for (let [key, value] of mapSettings) {
  console.log(`${key} = ${value}`);
}

// Return
// user = Sam
// topic = ES2015

JavaScript Evolution ECMAScript 6 - New Additional to Array

Assigning From Array to Local Variables

Typically we access array elements using index.
let users = ["Sam", "Tyler", "Brook"];
let a = users[0];
let b = users[1];
let c = users[2];
In ES2015, new implement in Array destructuring allows us to write less code.
let users = ["Sam", "Tyler", "Brook"];
let [a, b, c] = users;
If there is any value that not interested in, we can discard.
let users = ["Sam", "Tyler", "Brook"];
let [a, ,b] = users;
We can combine destructuring with rest parameters to group values into other Array.
let users = ["Sam", "Tyler", "Brook"];
let [first, ...rest] = users;
console.log(first); // Return "Sam".
console.log(rest); // Return a new Array ["Tyler", "Brook"]

Using for...of to loop over Array

The for...of statement iterates over property values, and it's a better way to loop over arrays and other iterate objects.

Here is the typical way we loop thru array using index.
let names = ["Sam", "Tyler", "Brook"];
for (let index in names) {
  console.log (names[index]);
}
Now, using for...of, we don't use the index.
let names = ["Sam", "Tyler", "Brook"];
for (let name of names) {
  console.log(name);
}

Finding an Element in an Array

Array find returns the first element in the Array that satisfies a provided testing function.
let users = [
  {login: "Sam", admin: false},
  {login: "Brook", admin: true},
  {login: "Tyler", admin: true}
];
let admin = users.find( (user) => {
  return user.admin;
});
console.log(admin); // Return {login: "Brook", admin: true}