Author: Shiva Charan Devabhaktuni

  • async & await in ES2017/ES8

    async

    Adding an async keyword to a function makes it asynchronous as the name itself suggests and it also return a promise instead of the value. We can define an ES6 function as async using the following syntax. This works with the old function syntax as well.

    let myFunc = async() => {
      return 'Hi I am async!';
    };
    console.log(myFunc());
    // logs Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "Hi I am async!"}
    
    /* Resolving a promise */
    myFunc().then((result) => {
      console.log(result);
    // logs: Hi I am async!
    }).catch((err) => {
      console.log(err);
    });
    

    await

    The await keyword can only be used inside an async function. When used, while calling an async function, it resolves the promise and returns the value.
    The above code can be made more readable, by using the await keyword.

    let myFunc = async() => {
      return 'Hi I am async!';
    };
    let finalSync = async() => {
      console.log(await firstAsyncFunc());
    // logs: Hi I am async
    };
    finalSync();
    

    Here is a live example of asynchronous functions in action. Although the first function is called first, we don’t have to wait until the promise is resolved to a result by await, instead we can see rest of the functions calls and their promises being resolved earlier.
    Code

    let firstAsyncFunc = async() => {
      setTimeout(function() {
        console.log('First');
      }, 3000);
    };
    let secondAsyncFunc = async() => {
      console.log('Second');
    };
    let thirdAsyncFunc = async() => {
      return 'Third';
    };
    let finalSync = async() => {
      await firstAsyncFunc();
      await secondAsyncFunc();
      console.log(await thirdAsyncFunc());
    };
    finalSync();
    

    Output

    Second
    Third
    First
    

    Demo

    Sequential calls vs Parallel calls

    The following is an example of sequential asynchronous function calls

    let finalSync = async() => {
      await firstAsyncFunc();
      await secondAsyncFunc();
    };
    finalSync();
    

    If you want to make asynchronous function calls simultaneously, then you could use Promise.all and supply it with an array of asynchronous functions and then use await to return the result after all the calls are made.

    let finalSync = async () => {
      await Promise.all([async1(), async2()]);
    }
    finalSync();
    
  • ES2016/ES7 in 5 Minutes

    The ECMAScript 2016 has just two small changes.

    Array.prototype.includes()

    Return type: boolean

    Usage

    let numbers = [1, 2, 3, 4];
    let arr = new Array('a', 'b', 'c', 'd');
    console.log(numbers.includes(2));
    console.log(numbers.includes(8));
    console.log(arr.includes('a'));
    

    Output

    true
    false
    true
    

    Demo

    This replaces the array.indexOf(element) which returns the index if the element is found or -1 if it isnt. This new function allows you to check for NaN (Not a Number) and this works on objects in a array too, but they must match the instance being passed.

    The Exponentiation Operator (**)

    Usage

    let num1 = 3;
    let num2 = 2;
    console.log(3 ** 2);

    Output

    9
    

    Demo

    This replaces the Math.pow(3, 2) function. This new operator allows for infix notation.

  • Vuex with vue-router and Bootstrap/jQuery

    This post talks about using the vue-router (official router for Vue.js 2) alongside Vuex (state management pattern + library).

    Using Vuex, gives you the ability to debug code easily, and switch between states in your chrome browser. For this you will need to install the Vue.js devtools chrome extension, and open the dev-tools in a page that uses Vue.js and then navigate to the Vue tab and choose the Vuex icon (usually 2nd from left).

    In the following code, the ability to add/delete widget objects is implemented using mutations in Vuex. Here mutations are synchronous calls that can alter the state. This state can be easily accessed through the mapGetters in Vuex. Following this pattern keeps the state management pretty clean in larger applications, where multiple parts of the applications get to access/alter the state.

    Note: You can also make asynchronous calls using actions in Vuex but, that part has not been included in the following code.

    I have used bootstrap for quick styling. The router is setup with the widgets view as default. This code was built using the default vue-cli webpack template, which makes life easier for running unit tests, end to end tests and also building production ready code.

    vuejs 2.0

    This is the default view of the demo application. Below you can view the debugging capabilities of Vuex.

    vuex

    Code (github)

  • Learn Angular CLI in 5 minutes

    Install

    Make sure you have node and npm installed and that they are available via the PATH variable on Windows.

    npm install -g @angular/cli

    Create a new application

    This following command will create a new application called collegestash in your current directory.
    This does npm install too by default. Here the –routing flag tells it to create a router and add it to the project. The –style scss also specifies that this project will be using scss (Saas) instead of css for styling.

    ng new collegestash --routing --style scss
     cd collegestash

    If you would like to be careful before you execute a command you can supply the -d flag which indicates a dry-run flag. The changes will not be written to disk, but you will be able to see the changes it will make in case the dry-run flag isn’t supplied.

    ng new cs -d
    
    
    installing ng You specified the dry-run flag, so no changes will be written. create .editorconfig create README.md create src\app\app.component.css create src\app\app.component.html create src\app\app.component.spec.ts create src\app\app.component.ts create src\app\app.module.ts create src\assets\.gitkeep create src\environments\environment.prod.ts create src\environments\environment.ts create src\favicon.ico create src\index.html create src\main.ts create src\polyfills.ts create src\styles.css create src\test.ts create src\tsconfig.app.json create src\tsconfig.spec.json create src\typings.d.ts create .angular-cli.json create e2e\app.e2e-spec.ts create e2e\app.po.ts create e2e\tsconfig.e2e.json create karma.conf.js create package.json create protractor.conf.js create tsconfig.json create tslint.json Project 'cs' successfully created.

    Component

    ng g c login
    

    or

    ng generate component login
    

    This generates a component called login in a separate folder.

    Service

    ng g s login
    

    or

    ng generate service login
    

    This generates a service called login but doesn’t add the provider, and generates it in the main folder. You need to specify --flat false to generate this in it's own folder. You can also the module in which you would like to include this by using the -m flag.

    ng g s login -m app.module --flat false
    

    If you know the folder where you would like to place the service. Then you could do the following to put it in a specific folder.

    ng g s login/login -m app.module
    

    Classes, Interfaces & enums

    Generate typescript classes, interfaces and enums.

    ng g cl models/classname
    ng g i models/interfacename
    ng g e models/enumname
    

    Pipes

    Generate a pipe.

    ng g p pipes/pipename

    Modules

    The following command generates a module called login in it’s own folder by default. No spec file is generated by default, hence we need to specify explicitly. You need to manually add this to your app.module to make sure they are linked together. Extra routing module gets created along with the required module.

    ng g m login –spec true --routing 
    

    Guard

    Generate a guard for routing.

    ng -g guard auth 
    

    Build

    This should build the application and output the files in build bundles with webpack runtime, app code, polyfills, styles, angular and other vendor files. You can supply the --prod flag to make sure the app is ready for production.

    ng build

    To be able to view sources, install the following and run the next command.

    npm i source-map-explorer –save-dev
    node_modules/ .bin/source-map-explorer dist/main.bundle.js
    

    ng build

    Build Environment vs Build Target

    Build Environment - Choosing an Environment
    Build Target - Refers to choosing whether or not to optimize.

    Serve

    This serves the app and opens it in your default browser.

    ng serve -o

    Add External Libraries

    You can use the angular-cli.json file and add them to styles and scripts arrays.

    Eject

    You can get away from the angular-cli dependency in the project.

    ng eject

    Unit Tests

    Runs all unit tests in the project, namely *.spec.ts files. Watches for changes and re runs them. So if you open this in a new terminal then this will, automatically detect the changes you make in the other terminal to the files in the project.

    ng test
    ng test -sr

    Setting the single run flag, can be best for use in Continuous Integration.
    (or)

    ng test -w false

    Setting watch to false gets the same result as above.

    ng test -cc
    

    The above command is for code coverage which is in the coverage folder by default unless something different is specified in the angular-cli.json file.

    End to end Testing

    This runs the end to end tests.

    ng e2e
  • Merge 2 sorted Arrays Inplace (JavaScript)

    Time complexity: O(n)
    Here n represents the sum of the lengths of both the arrays.

    Code

    // Merge 2 sorted Arrays Inplace (JavaScript)
    
    var a = [1, 2, 3];
    var b = [4, 5];
    
    var sort = function(a, b) {
      var alen = a.length - 1;
      var blen = b.length - 1;
      var index = alen + blen + 1;
      while (blen >= 0) {
        if (a[alen] >= b[blen])
          a[index--] = a[alen--];
        else
          a[index--] = b[blen--];
        if (alen < 0) {
          while (blen >= 0) {
            a[index--] = b[blen--];
          }
          break;
        }
    // if (blen<0) a's contents are already in place, so we don't need to worry about them.
      }
      return a;
    }
    
    console.log(sort(a, b));
    

    Output

    [1,2,3,4,5]

    Demo

  • How to fix ng-if error in AngularJS

    The ng-if directive has it’s own scope, so if you have issues with why a certain component is added or removed from the DOM even though your condition is true. It is probably because you aren’t referring to the right property. So this is how that can be fixed easily by referring to the parent scope.

    Some content here...
  • User Registration Form using PHP 7.1.5

    github

    The first step would be to create a new MySQL database and then add a user with all privileges except GRANT. Now replace the values in the file db_connection.php with those.

    $link = new mysqli("localhost","user-name","user-password", "your-database-name");

    Now once you are done with this run the file createTables.php from the browser. You should see a success message. If not make sure you have entered the right credentials and that MySQL server is running.

    Now, if you don’t have a registration form UI (HTML5+js) then you can use postman from the chrome web store or any other testing tool.

    You can use the following JSON to post to userRegistration.php

    {
    "fname": "Shiva",
    "lname": "Charan",
    "email": "shiva007charan@yahoo.co.in",
    "gender": "m",
    "pwd": "Password"
    }

    This should give you a success message when executed once and you should see the row added to your database in your PhpMyAdmin. If executed more than once, then you will get a message “User already exists”.

    Note: Make sure that you have PHP 7.1.5 installed. This program works on HHVM as well.

  • How to Automate your Releases using only git & crontab?

    You can easily automate your code deployment using crontab and git.
    Lets assume you push your code to your remote PROD branch and a cronjob on prod keeps running or runs at a certain time checks if your branch is behind the remote or not and if it is, then it pulls code and restarts your application.

    To start off make sure you have both git and a git repository. If you do then you can skip to Automation, if not then start by installing git and initializing a git repository on your local. For Ubuntu, here is how,

    sudo apt-get update
    sudo apt-get install git
    cd /your-path-to-git
    sudo mkdir project
    cd project
    git init
    git remote add origin https://github.com/user/repo.git
    git pull origin
    git checkout -b branch-name
    git add *
    git commit -a -m "initial commit"
    git push origin branch-name
    

    Note: replace ‘https://github.com/user/repo.git’ with your HTTPS git repo URL.
    If you see an error that remote already exists then you can use the following to remove it and then add your new repository under the same name or you can add a new name

    git remote rm origin
    git remote add origin https://github.com/user/repo.git
    

                                                              or

    git remote add newremotename https://github.com/user/repo.git
    git remote add origin https://github.com/user/repo.git
    

    Automation

    Replace ‘/your-path-to-git/project’ with the path to your git project.
    replace ‘branch-name’ with the branch you want to automate.
    Save this in a file called automate.sh.

    cd /your-path-to-git/project
    
    git checkout -b branch-name
    git remote update
    
    UPSTREAM=${1:-'@{u}'}
    LOCAL=$(git rev-parse @)
    REMOTE=$(git rev-parse "$UPSTREAM")
    BASE=$(git merge-base @ "$UPSTREAM")
    
    if [ $LOCAL = $REMOTE ]; then
        echo "Up-to-date"
    elif [ $LOCAL = $BASE ]; then
        echo "Need to pull"
        sh pull_code.sh     
    fi
    

    Replace both the occurences of ‘branch-name’ with your required branch name and then save the code in a file named ‘pull_code.sh’ in the same directory as the ‘automate.sh’.

    git reset --hard origin/branch-name
    git pull branch-name

    If you run the file using the following command then it should check for changes in the remote branch and pull them. Make sure to change ‘branch-name’ to whatever branch name you are using.

    sudo sh automate.sh "remote/origin/branch-name"

    Make the two files executable by the user

    sudo chmod u+x *.sh
    

    Cronjob

    The next step would be to create a cronjob for this using crontab.
    Use the following command for that,

    crontab -e

    Then hit ‘i’ start editing using vi (Visual Editor – The default editor that comes with the UNIX operating system).

    # MAILTO="your-email@example.com"
    # This is a comment
    * * * * * /yourpath/automate.sh > /dev/null 2>&1
    

    You can add your email in the MAILTO parameter.  But this works only if  you don’t have logging set, here we have set all the output and standard error output to null, so it won’t work. For the email functionality to work, you need to have the mail server setup for this.

    To log all the output to a file, replace the job with the following.

    * * * * * /yourpath/automate.sh >> /var/log/cron.log 2>&1

    After adding the above code to your crontab, use the following to write changes and quit the vi.
    ‘ESC’ + ‘wq!’

    This job is set to run every minute. It should have already output some data into your logs. Just to be sure we can restart the cron service once after the changes are saved.

    sudo service crond restart
  • Handling Date objects in Javascript

    Handling date objects in javascript can be very tricky at times. Here are few tricky scenarios.

    Comparision with ‘===’

    When you compare two date objects that contain the exact same time stamp using ‘===’, then this will not be true as two objects can only be equal if they refer to the same object.

    var date1 = new Date('2017-05-19T01:56:09.218Z');
    var date2 = new Date('2017-05-19T01:56:09.218Z');
    
    if(date1===date2) 
       console.log('yes');
    else 
       console.log('no');
    

    Output

    no

    Demo

    The solution to this, is to convert this to some other format like date.getTime() or date.getISOString(), etc. Here is the example implementation of that.

    var date1 = new Date('2017-05-17T14:48:12.000Z');
    var date2 = new Date('2017-05-17T14:48:12.000Z');
    if (date1.toISOString() === date2.toISOString()) {
     console.log('yes');
    }

    Output

    yes
    

    Demo

    Copying a Date Object

    When you try to copy date objects like the following example, then both the variables refer to the same date objects and whatever changes you make on either of them reflects on the other, which is not the required outcome

    var date1 = new Date('2017-05-17T14:48:12.000Z');
    var date2 = date1;
    date1.setHours(5, 30, 0, 0);
    console.log(date2);
    console.log(date1);

    Output

    Wed May 17 2017 05:30:00 GMT-0400 (Eastern Daylight Time)
    Wed May 17 2017 05:30:00 GMT-0400 (Eastern Daylight Time)
    

    Demo

    To solve this we need to create a new Date object while assigning the date to a new variable.

    var date1 = new Date('2017-05-17T14:48:12.000Z');
    var date2 = new Date(date1);
    date1.setHours(5, 30, 0, 0);
    console.log(date2);
    console.log(date1);

    Output

    Wed May 17 2017 10:48:12 GMT-0400 (Eastern Daylight Time)
    Wed May 17 2017 05:30:00 GMT-0400 (Eastern Daylight Time)
    

    Demo

  • Sort javascript objects based on multiple properties

    When you want to sort javascript objects based on 2 properties,  you can use the following code. In this example here we have an array of people (objects) here. I want to sort them by first name and then by their last names. So, what I do in my compare function to get the required output is to sort them by their last names, only when their first names are equal.

    var people = [{
     "fname": "shiva",
     "lname": "kiran"
    }, {
     "fname": "aru",
     "lname": "wind"
    }, {
     "fname": "shiva",
     "lname": "charan"
    }];
    
    var compare = function(a, b) {
     var ret = a.fname.localeCompare(b.fname)
     if (ret === 0) {
     return a.lname.localeCompare(b.lname);
     }
     return ret;
    };
    
    people.sort(compare);
    console.log(people);

    Output

     [{
     "fname": "aru",
     "lname": "wind"
    }, {
     "fname": "shiva",
     "lname": "charan"
    },
    {
     "fname": "shiva",
     "lname": "kiran"
    }]
    

    Demo

    If you would like to use integers then, this example with ages would help. Here the people are sorted by first names and then by their ages.

    var people = [{
     "fname": "shiva",
     "lname": "kiran",
     "age": 20
    }, {
     "fname": "aru",
     "lname": "wind",
     "age": 21
    }, {
     "fname": "shiva",
     "lname": "charan",
     "age": 19
    }];
    
    var compare = function(a, b) {
     var ret = a.fname.localeCompare(b.fname)
     if (ret === 0) {
     return a.age - b.age;
     }
     return ret;
    };
    
    people.sort(compare);
    console.log(people);

    Output

    [{
     "fname": "aru",
     "lname": "wind"
     "age": 21
    }, {
     "fname": "shiva",
     "lname": "charan"
     "age": 19
    },
    {
     "fname": "shiva",
     "lname": "kiran",
     "age": 20
    }]
    

    Demo

    If you would like to sort objects in descending order (strings or integers), then just return the negative of the result.

    var people = [{
     "fname": "shiva",
     "lname": "kiran",
     "age": 20
    }, {
     "fname": "aru",
     "lname": "wind",
     "age": 21
    }, {
     "fname": "shiva",
     "lname": "charan",
     "age": 19
    }];
    
    var compare = function(a, b) {
     var ret = a.fname.localeCompare(b.fname)
     if (ret === 0) {
     return b.age - a.age;
     }
     return -1*ret;
    };
    
    people.sort(compare);
    console.log(people);
    

    Output

    [{
     "fname": "shiva",
     "lname": "kiran",
     "age": 20
    }, 
    {
     "fname": "shiva",
     "lname": "charan"
     "age": 19
    },
    {
     "fname": "aru",
     "lname": "wind"
     "age": 21
    }] 
    

    Demo