Promise in JavaScript

JavaScript is a single-threaded or synchronous programming language but with promises we can make it look like multi-threaded or asynchronous programming language. Imagine a function waiting for a network request to complete which takes more time. Meanwhile entire execution freezes at that time we need asynchronous operations. Prior to promises, events and callback functions are used. But events and callback functions create callback hell and can lead to unmanageable code. It is not easy to handle multiple callbacks at a time. Events are not good in asynchronous operations. So obviously, promise became the best choice for handling asynchronous operations.

In JavaScript, promise is a way of handling asynchronous operations. It is an object that holds the future value of an asynchronous operations. It is helpful in finding out whether a asynchronous operation is successfully completed or not.

Benefits of Promises:

  • Improves code readability.
  • Better at handling multiple callback functions at the same time and avoiding callback hell situation.
  • Better control flow in asynchronous logic
  • Improves error handling

Difference between promises and event handlers:

  • A promise can never fail or succeed twice. It can be only once.
  • A promise can never switch from success to fail or fail to success.
Promise has three states:
  • Pending
  • Fulfilled
  • Rejected

Pending – Initial state. A promise starts here.

Fulfilled – If operation was successful ends in fulfilled state.

Rejected – If operation was fail ends in rejected state.

A promise is settled if it is either fulfilled or rejected but not pending.

Create a promise:

To create a promise we use constructor Promise()

let promise = new Promise(function(resolve,reject){
	//do something
});

Promise() constructor takes function as an argument. This function accepts two functions resolve() and reject(). If promise is successful returns resolve() function and by failure returns reject() function.

Example:
const count = true;

let countVal = new Promise(function (resolve, reject) {
    if (count) {
        resolve("There is a count value.");
    } else {
        reject("There is no count value");
    }
});

console.log(countVal);
Output:

Promise { ‘There is a count value.’ }

In above example promise is resolved if count is true.

JavaScript Promise chaining:

Promises are useful in handling more than one asynchronous task one after another. For that we have promise chaining. We use then(), catch() and finally() methods.

JavaScript then() method:

then() method is used with callback when promise is successfully fulfilled or resolved.

Syntax:
.then(function(result){
        //handle success
    }, function(error){
        //handle error
    })
Example:
new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000); 

}).then(function(result) { 

  console.log(result); 
  return result * 3;

}).then(function(result) { 

  console.log(result); 
  return result * 4;

}).then(function(result) {

  console.log(result); 
  return result * 6;
});
Output:

1

3

12

Here all operations returns the result to the next then on the chain and this continues till last element and final result is returned.

JavaScript catch() method:

catch() is used when a promise is rejected or if an error occurs. It is used as error handler whenever at any step there is chance of getting error.

Syntax:
.catch(function(error){
        //handle error
    })
Example:
// returns a promise
let countValue = new Promise(function (resolve, reject) {
   reject('Promise rejected'); 
});

// executes when promise is resolved successfully
countValue.then(
    function successValue(result) {
        console.log(result);
    },
 )

// executes if there is an error
.catch(
    function errorValue(result) {
        console.log(result);
    }
);
Output:

Promise rejected.

MethodDescription
Promise.all()Waits for all promises to be resolved or any one to be rejected
Promise.allSettled()Waits until all promises are settled
Promise.any()Returns the promise value as soon as any one of the promises is fulfilled
Promise.race()Wait until any of the promises is resolved or rejected
Promise.reject()Returns a new Promise object that is rejected for the given reason
Promise.resolve()Returns a new Promise object that is resolved with the given value
catch()Appends the rejection handler callback
then()Appends the resolved handler callback
finally()Appends a handler to the promise

Generator in JavaScript

In ECMA2015 generators are introduced in javascript. Functions in Javascript run until return or end. Generators run until yield or return or end. Generator is a process that can be passed and resumed and can yield multiple values. It provides a new way of working with functions and iterators.

Using a generator:

  • You can stop the execution of a function from anywhere inside the function.
  • Continue executing from pause position.

Regular function return only one single value or nothing. It is executed upto completion. It cannot pause in middle and continue from pause position.

On the other hand generators can yield multiple values, one after another on demand. It works with iterators, to create a data stream with ease.

Create Generators:

To create a generator, we define a generator function with *. The objects of generator function are called generators.

Syntax:
// define a generator function
function* generator_function() {
   ... .. ...
}

// creating a generator
const generator_object = generator_function();

This generator function can also be defined in expressions

// Generator function expression
const generatorFunction = function*() {}
Using yield and next():

Generator function once called returns generator object, which holds generator iterable that can be iterated using next() method or for … of loop.

Every next() method executes every line of code until next yield it encounter and suspends its execution temporarily.

// generator function
function* generatorFunc() {

    console.log("1 invoke");
    yield 1;
    
   console.log("2 invoke");
    yield 2;
}

// returns generator object
const generator = generatorFunc();
console.log(generator.next());
Output:

1 invoke

{ value: 1, done: false }

Here a generator object is created. When generator.next() is called it executes upto yield 1 and pause the execution.

Using multiple yields:
// generator function
function* generatorFunc() {

    console.log("1 invoke");
    yield 1;
    
   console.log("2 invoke");
    yield 2;
   console.log("3 invoke");
}

// returns generator object
const generator = generatorFunc();

console.log(generator.next());
console.log(generator.next());
console.log(generator.next());
Output:

1 invoke

{ value: 1, done: false }

2 invoke

{ value: 2, done: false }

3 invoke

{ value: undefined, done: true }

Here after first generator.next() executes 1 invoke upto yield 1 and pause.

Second generator.next() executes from pause position and executes 2 invoke upto yield 2 and pause again.

Third generator.next() executes from pause position and all yields are accessed so returns { value: undefined, done: true }

Using for… of loop:

Since generators are iterables we use for … of loop.

// generator function

function* generatorFunc() {

    console.log("1 invoke");

    yield 1;
console.log("2 invoke");

    yield 2;

}

// returns generator object

const generator = generatorFunc();

for ( const g of generator){

   console.log(g);

}
Output:

1 invoke

1

2 invoke

2

Generator methods:
MethodDescription
next()Returns a value of yield
return()Returns a value and terminates the generator
throw()Throws an error and terminates the generator
Generator states:

The next table lists the possible states of a Generator object:

StatusDescription
suspendedGenerator has halted execution but has not terminated.
closedGenerator has terminated by either encountering an error, returning, or iterating through all values.
Return vs yield keyword:
return keywordyield keyword
returns the value and terminates the functionreturns the value and pause the function
available in both normal and generator functionavailable only in generator function
Using return :
// generator function
function* generatorFunc() {

    yield 1;

   return 22;

    yield 3;
}
// returns generator object
const generator = generatorFunc();

console.log(generator.next());
console.log(generator.next());
console.log(generator.next());
Output:

{ value: 1, done: false }

{ value: 22, done: true }

{ value: undefined, done: true }

We can use return() method instead of return keyword as generator.return()

Here when return statement is encountered it returns the value, done is set to true and terminates the function and return nothing after that.

Generator throw() method:
// generator function
function* generatorFunc() {
    yield 100;
    yield 200;
}

// returns generator object
const generator = generatorFunc();
console.log(generator.next());

// throws an error
// terminates the generator
console.log(generator.throw(new Error('Error occurred.')));
console.log(generator.next());
Output:

{ value: 100, done: false }

Error: Error occurred.

Hoisting in JavaScript

Hoisting is a default behavior in JavaScript and not a feature. Here it allows us to use the variables and functions before declaring it. All the declarations of variables and functions are moved to the top of the scope. In other programming or scripting languages we cannot use a variable or function before declaring it.

In Javascript, compiler moves all variable and function declarations to the top so there won‘t be any error.

Lifecycle of a variable:

Declaration – Registers a variable in the corresponding scope.

Initialization – Allocates memory for a variable.

Assignment – Assign a specific value to the variable.

In Javascript only keyword var is hoisted and let and const are not hoisted.

Variable hoisting:

As said before only keyword var is hoisted.

//variable hoisting
a = 10;
console.log(a);
var a;
Output:

10

This above code will be rearranged in memory as declaration moves to top. So it works like,

var a;
a = 10;
console.log(a);

Now, what will happen if we try to access a variable before initialization?

console.log(a);

var a = 10;
Output:

undefined

It is because only declaration is hoisted that is move to the top but initialization is not hoisted. So, the variable is assigned undefined value if we try to access before initialization

The above code will be in executed in memory as follows and return undefined

var a;
console.log(a);
a = 10;

Now, what will happen if we try to use a variable that is not declared?

This can happen in cases where the number of lines of code is large and we cannot find the variables declared.

cosole.log(a);
a = 10;

Here reference error is thrown.

Keypoints:
  • undefined value is assigned when we try to access a variable before initialization.
  • Reference error occurs when we use a variable that is not declared

Function hoisting:

Here function declaration moves to the top of the scope.

var a = 10;
add(); // called before declaration
function add(){
  b = 20;
  console.log(a+b);
  var b;
}
console.log(b); // variable b is hoisted inside the function

Here the function declaration is moved to top. Variable a is declared outside so global scope but variable b is declared inside the function so it will be hoisted inside the function. Variable b is moved to the top of the function not outside the function scope. It has local scope. If we try to access a variable b outside the function it will throw reference error.

Another thing to remember is only function declaration is hoisted and function expressions are not hoisted.

var a = 10;
add();
var add =function(){ // function used in an expression
  b = 20;
  console.log(a+b);
  var b;
}

This will throw type error.

== vs === in JavaScript

In JavaScript for checking equality or comparison we have two operators.

  • == Double equals operator known as loose equality or abstract comparison
  • === Triple equals operator known as strict equality or strict comparison

Now the main difference between two operators is that == does type coercion before comparison but ==== does not convert and compares as it is.

Type coercion:

Type coercion is automatic or implicit conversion of one data type to another. It is similar to type conversion and the only difference is type conversion can be implicit or explicit. But type coercion can only be implicit.

Both comparison operators return Boolean value TRUE or FALSE

== or === Operator

If both are number data type it returns TRUE only when both value matches otherwise FALSE

var a = 10;
var b = '10';
console.log(a == b);
console.log(a === b);
Output:

True

False

If a string is compared to number, number gets converted to string and then compared

Which comparison operator should I use?

Always use strict comparison operator (===) as it will compare both the operand and data type. Using loose comparison operator (==) will lead to strange results in programming.

For example,

Using == operator
false == 0             // true
false == ""            // true
0 == ""                // true
undefined == null      // true
[] == false            // true
[] == 0                // true

It performs type coercion and returns the result. But originally each one is of different data type 0 is number, false is Boolean type.

false === 0             // false

false === ""            // false

0 === ""                // false

undefined === null      // false

[] === false            // false

[] === 0                // false

Points to note:

  • === does not coercs and just compares the operands as it is and returns the results. So it is always best to use === operator
  • == does implicit coercion and convert from one type to  another implicitly leading to strange results.

How to find the OData model version from the sap.ui.table.Table instance

Steps to be followed:

  1. Get the instance of table sap.ui.table.Table
  2. Get the Binding instance using the getBinding method of table instance
  3. Get the path of the OData Model using the getPath method of the ODataListBinding
  4. Get the model instance using the getModel() method of the ODataListBinding
  5. The OData version is defined in the metadata. so using the getMetadata() method of the model instance, the OData version can be determined
var bindingInstance = uiTableInstance.getBinding('rows')
var sPathOfModel = uiTableInstance.getBinding('rows').getPath()
var modelInstance = uiTableInstance.getBindng('rows').getModel(sPathOfModel)
modelInstance.getMetadata() ===> This will get the sap.ui.model.odata.v2.ODataModel version.

Difference-null and undefined

When writing my previous article nullish coalescing operator, i learned about the differences between null and undefined. Before that i thought both are more or less same but after getting to know about falsy values in javascript. Now i know the difference between them.

Null:

In English the literal meaning of null is having no value. null indicates the intentional absence of value in programming. null is manually assigned by programmers to variable which is declared, initialized and currently hold no value in Javascript. But a value can be expected in future. When we assign null to a variable it is empty or blank. null is of object data type in javascript. An object can be emptied by assigning it to null.

Syntax:
var a = null;

Here we have assigned value null to variable a.

undefined:

undefined means ‘not defined’. Here we declare a variable and does not assign a value to it. The value of undefined variable is set by javascript as undefined.

Syntax:
var a;

Here a variable is created at runtime and if we haven’t passed an argument for a function parameter default value is undefined. When a function doesn’t return a value it is undefined.

Similarites:

  • null and undefined denote the absence of value
  • Both are primitive Javascript types
  • They are falsy values
  • undefined and null are loosely equal (==)

null vs undefined:

Using typeof:

When we use typeof it returns object as type for null and undefined as type for undefined variable

var a = null;
console.log(typeof(a));
var b;
console.log(typeof(b));

Output:

object

undefined

Using primitive operations:

In primitive operations null is converted to 0 and undefined to NaN.

var a = 10;
var b;
var c = a+b;
console.log(c);

Output:

NaN

var a = 10;
var b = null;
var c = a+b;
console.log(c);

Output:

10

nullundefined
It is an assigned valueIt is not an assigned value
It represents an empty or unknown valueHere variable is declared but not assigned any value
It is a primitive type object in javascriptIt is a ES1 feature and is a primitive type by itself
null indicates absence of value for a variableundefined indicates absence of variable itself
Using typeof returns objectUsing typeof returns undefined
By primitive operations null is converted to zero (0)By primitive operations undefined is converted to NaN

Why Javascript needs nullish coalescing operator?

Javascript provides a double question mark operator (??) which is known as nullish coalescing operator. It is introduced in ES2020. It is a logical operator.

According to MDN, nullish coalescing operator(??) is defined as “a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined and otherwise returns its left-hand side operand.

Nullisch coalescing is used to set default values when dealing with null or undefined.

In Javascript we already have a logical OR operator || which returns the truthy values.

Here nullish coalescing ?? deals with falsy values.

So, now what are falsy values in javascript?

  • Null
  • Undefined
  • 0
  • NaN
  • False
  • ” “

Using logical OR operator ||:

let a = 0;
let b = 2;
console.log(a||b); //checks the first true value.

Output:0

let a = false;
let b=2;
console.log(a||b); //checks the first true value.

Output: 2

let a = 1;
let b=2;
console.log(a||b); // checks the first true value.

Output: 1

Using nullish coalescing operator:

let a = 0;
let b = 2;
console.log(a??b);

Output: 0

let a = false;
let b=2;
console.log(a??b);

Output: false

let a = null;
let b = 2;
console.log(a??b);

Output: 2

let a = undefined;
let b = 2;
console.log(a??b);

Output: 2

let a = 1;
let b=2;
console.log(a??b);.

Output: 1

For nullish operators only null and undefined are falsy values.

We often use logical operators for assigning a default value to a variable. Nullish coalescing operator is used when you want to evaluate the second expression only when first expression is null or undefined.

Browser Support:

The browsers supported by nullish coalescing operator are:

  • chrome 80
  • firefox 72
  • safari 13.1
  • opera 67
  • edge 80

Key points to remember:

  • We cannot chain with AND && or OR || operator.
  • ?? operator returns the second value if first value is null or undefined.

7 Statements to loop in JavaScript?

Generally, in programming languages loops are useful in repeating a block of code. Loops are repeated set of actions which runs based on a condition. The loop continues to run until the condition returns a FALSE. The basic idea of loop is to save time and effort. To loop in javascript we have 7 statements which belong to two categories.

There are mainly two types of loops:

  • Entry controlled loop:

The condition is tested before entering the loop and the control is transferred into the loop only if the condition is TRUE. Example: for and while loops.

  • Exit controlled loop:

The condition is tested at the end of the loop. The loop is executed at least once irrespective of whether the condition is TRUE or FALSE. Example: do-while loop.

1. for loop:

    The most frequently used loop in javascript.

    Syntax:
    for(initialization; condition; iterator)
    {
    // code to execute
    }
    

    It consists of three parts. First part initialization is executed only once at the start of the loop and initializes the loop. The second part is a condition when it is evaluated to TRUE, the loop gets executed and terminates when it is FALSE. The third part is an iterator which usually a increments or decrements after each iteration. For loop is more readable as all the expressions lie on a single line. If the number of iterations is known we use for loop.

    Example:
    var sum = 0;
    for (var i = 1; i <= 10; i++) {
        sum = sum + i;
    }
    console.log("Sum = " + sum);
    

    Output:

    Sum = 55

    2. for-in loop:

    for-in loop iterates over the properties of an object. For each property the code in the block is executed. It iterates over the keys of an object which have their enumerable property to TRUE. It iterates over all the enumerable properties including inherited enumerable properties.

    Syntax:
    for( property in object){
    //code
    }
    
    Example:
    var employee = {name: "Tom", age: 25, salary: 1000};
    for (var item in employee) {
        console.log(employee[item]);  
    }
    

    Output:

    Tom

    25

    1000

    3. for.. of loop:

                     for… of loop is used for iterating over iterable objects like arrays and strings.

      Syntax:
      for(variable of object){
      
      //code
      
      }

      It can be used for iterating over arrays, strings, maps and set.

      Example:
      var employee=['Tom','Anna','Tim','Jones']
      for (let item of employee)
          {
              console.log(item);
          }
      

      Output:

      Tom

      Anna

      Tim

      Jones

      With Map:
      const emp = new Map();
      emp.set(1, "Tom");
      emp.set(2, "Anna");
      
      for (let i of emp) {
        console.log(i);
      }
      

      Output:

      Tom

      Anna

      With Set:
      const emp = new Set();
      emp.add(1);
      emp.add("Tom");
      
      for (let i of emp) {
        console.log(i);
      }
      

      Output:

      1

      Tom

      4. While Statement:

      While loop starts by evaluating the condition. If it is TRUE the loop gets executed. If it is FALSE the loop terminates.

      Syntax:
      While(condition)
      {
      //statement
      }
      
      Example:
      var sum = 0;
      var number = 1;
      while (number <= 10) {     //condition
          sum += number;         
          number++;              //iterator
      }
      console.log("Sum = " + sum);  
      

      Output:

      55

      5.do… while statement:

        Here the condition is checked at the end of the loop. The loop is executed atleast once irrespective of condition being TRUE or FALSE.

        Syntax:
        do {
          // statement
        } while (condition);
        
        Example:
        var sum = 0;
        
        var number = 1;
        
        do{    
        
            sum += number;        
        
            number++;              //iterator
        
        }while (number <= 10) //condition
        
        console.log("Sum = " + sum);

        Output:

        55

        6. break statement:

          Whenever a break statement is seen in the loop, it exits the loop without executing other statements in the loop. Control is transferred to the statement following the loop.

          Syntax:
          for(initialization; condition; iterator){
          // code
          If(condition){
          break;
          }
          //code
          }
          
          Example:
          for(i=1;i<10;i++){
              if(i==5){//break statement
                  break;
              }
              console.log(i);
          }
          

          Output:

          1

          2

          3

          4

          7.continue statement:

            continue statement is used to break the current iteration of the loop and the control flow of the program goes to the next iteration.

            Syntax:
            for(initialization; condition; iterator){
            //code
            if(condition){
            continue;
            }
            //code
            }
            
            Example:
            for(i=1;i<10;i++){
                if(i==5){//continue statement
                    continue;
                }
                console.log(i);
            }
            

            Output:

            1

            2

            3

            4

            6

            7

            8

            9

            4 methods to search through arrays in JavaScript

            Before ECMA6, we have to search through arrays using for loops. Now we have specific methods to search through arrays.

            Methods to search through arrays:
            • Array.includes()
            • Array.indexOf()
            • Array.find()
            • Array.filter()

            Array.includes():

                           It returns a true if a value exists in an array otherwise false

            Syntax:
            includes(searchElement)
            
            includes(searchElement, fromIndex)

            fromIndex is optional. Default is 0. It determines from which index to begin comparison

            const arr=[2,4,6,8]
            
            console.log(arr.includes(6))
            
            console.log(arr.includes(10))
            Output:

              True

            False

            In the above example when we search for the element 6 from index 3 it will return false. As the element 6 is in index 2

            const arr=[2,4,6,8]
            
            console.log(arr.includes(6,3))
            Output:

            False

            Array.indexOf():

                           This method returns the first index at which a given element can be found and -1 if it is not there. It starts at a specified index and search from left to right. By default, start from first element and ends at last element.

            Syntax is similar to includes()

            const indexOfElement = array.indexOf(element, fromIndex)

            element – element you are searching

            fromIndex – position or index from where you want to start the search

            Example:

            const emp=["Anna","Tom","Sam","Henry","Jack"]
            let index = emp.indexOf("Henry", 2);
            console.log(index)
            
            Output:

            3

            Array.find():

            This method is used to find the first element that meets the certain conditions. If elements do not satisfy the condition, it returns undefined. It is like filter method takes callback as an argument and returns the first element that satisfies the callback condition.

            Syntax:
            let element = array.find(callback);

            callback is the function which is called on each element of the array. This has following parameters.

            element- current element being processed.

            index- index of current element

            array- the array find() is called on.

            find() is an iterative method.

            Example:
            const arr = [10, 20, 45, 120, 99];
            const found = arr.find(element => element > 100);
            console.log(found);
            
            Output:

            120

            Array.filter()

            This method will return a shallow copy of elements in an array that satisfies the given condition.

            Syntax:
            let newArray = array.filter(callback);

            newArray is the array created with elements that satisfy the conditions.

            array- array on which filter method is used.

            Callback- function that is applied to each element of the array.

            If no element matches the condition then an empty array is returned.

            When we want to return only one element that matches the condition then we use find() method.

            Example:
            const arr = [10, 20, 108, 120, 99];
            const found = arr.filter(element => element > 100);
            console.log(found);
            
            Output:

            [108,120]

            Points to remember:
            • includes() method is used to check whether a particular element present in an array. It returns a Boolean value TRUE or FALSE indicating the element is present or not.
            • indexOf() method is used to search for a particular element in an array and return the index of that element. It returns -1 if element is not there.
            • find() method is used to search for the first element that satisfies the given condition. It searches if atleast one element satisfies the condition and returns undefined if not satisfied.
            • filter() method is used to search for multiple elements and returns all the elements that satisfies the condition in a new array. It returns a empty array if no element satisfies.