Advanced Javascript Concepts
This article explains how to use most advanced, but must learn Javascript concepts including Prototypes, Proxies and Callbacks.
Prototypes
Objects and arrays in Javascript, inherits properties and methods from prototype object.
let numbers = {1, 2, 3}
console.log(numbers);
When you check console.log() of an Array or Object, You’ll see an internal property named __proto__
which points to the prototype object of the parent function. For example, an array inherits set of prototype methods from it’s parent Array
function.
If we look at Array.prototype
, we will see same set of methods and properties exposed through property __proto__
.
Now if we add a new method to the Array
function, it will be inherited in any array you create.
Similarly, you can access or modify prototype
object of custom functions you create, and it will be inherited by the instances.
Promises
Promise
is an object in Javascript used to represent completion or failure of an asynchronous operation, and it’s resulting value.
A promise can be defined as below;
let promise = new Promise(function(resolve, reject) {
// executor
});
Promise accepts a function (executor) as argument and it accepts two functions named resolve
and reject
as given in above example.
Executor can be a long running operation like database execution or web service call out. If operation is successful, resolve(value) can be called, else reject(error).
A promise can be in one of three states. Initially it will be in “pending” state, then it will be changed to “fulfilled” when resolve() or “rejected” when reject() is called.
Here is a sample function returning a promise.
function promiseMe() {
return new Promise(function (resolve, reject) {
setTimeout(() => resolve("completed"), 10000);
});
}
Syntax for consuming a promise.
.then(function(success){
//handle success
}, function(error){
//handle error
})
This is a sample code for consuming promiseMe()
function created above. If resolve()
is called it will execute console.log(success)
and if reject(), then it will run console.log(error)
.
let trust = promiseMe();
trust.then(
success => console.log(success),
error => console.log(error)
);
Alternatively, reject can be handled with catch() and it will be invoked when a promise is either rejected or some error has occurred in execution.
let trust = promiseMe();
trust.then(
success => console.log(success)
).catch(error => {
console.error(error)
})
If you need some code to be executed when either success or rejected, you can use finally() as below.
let trust = promiseMe();
trust.then(
success => console.log(success)
).catch(error => {
console.error(error)
}).finally(() => console.log("final promise"))
Async/await
Async
and await
functions were introduced in ES8 which make asynchronous code easier to write and to read afterwards.
Basic async function can be defined as below.
async function hello() { return "Hello" };
hello();
It can be further simplified with an arrow function.
let hello = async () => { return "Hello" };
hello();
When executed, above function returns a promise. To consume async function, .then() can be used.
hello().then((value) => console.log(value))
or
hello().then(console.log)
await keyword can be used inside async function to pause execution of code until promise has fulfilled.
function promiseMe() {
return new Promise(function (resolve, reject) {
setTimeout(() => resolve("completed"), 10000);
});
}
async function myPromise() {
const msg = await promiseMe();
console.log('Message:', msg);
}