# Tips for quick recall

1.href vs src: href resources are loaded based on a trigger src resources are loaded automatically.

2. Ajax (Asynchronous JavaScript And XML): update a web page without reloading the page

Using XMLHttpRequest to create a http request and send to sever, and then server send data back to browser, and finally update page content

3.splice usage for remove one element from array:

var list = [1,2,3,4,77,5,6];
var removeTheOne = (value) => {
  for(var i = 0; i < list.length; i++){
    if(list[i] === value) {
      list.splice(i, 1);
    }
  }
  return list;
};

var afterRemove5 = removeTheOne(5);
console.log(afterRemove5); // [1,2,3,4,77,6]

4.session storage vs local storage vs cookie

Common: all of these 3 are stored inside browser ..

  • cookie:

    • Capacity: 4kb (much more smaller)
    • Support: Since from HTML 4
    • Browser Tab: Any
    • Expires: Manually set
    • Storage Location: Browser & Server
    • Send with requests: Yes
  • local storage:

    • Capacity: 10mb (Maximum support)
    • Support: Since from HTML 5
    • Browser Tab: Any
    • Expires: Never
    • Storage Location: Browser only
    • Send with requests: No
  • session storage:

    • Capacity: 10mb (also Maximum support)
    • Support: Since from HTML 5
    • Browser Tab: Same tab only
    • Expires: On tab close
    • Storage Location: Browser only
    • Send with requests: No
// Short tips:

// local storage: expires until you delete it
// session storage: expires when you close current tab
// cookie: manually set expire time (eg: set a year, very very future ..)
// eg: document.cookie = 'name=damon; expires=' + new Date(2021, 12, 12).toUTCString();

// cookie will be sent every time when user sends API request to the server, thats why cookie needs to be smaller size

// when deal with server, use cookie, deal with browser use session.local storage

5. Please watch this video for recall token && session based authentications

  • Session based authentication: stateful, using cookie

    • Flow:
    1. user submit login credentials (email + password)
    2. server verifies user input against DB
    3. server create a temporary user session
    4. server -issues a cookie with session ID (eg: Set-Cookie in header)
    5. user sends cookie with each request
    6. server validate user request via session store to check whether user cookie is whether valid or not
    7. when user logout, server removes session information, including with cookie
  • Token based authentication: stateless, using JWT, OAuth and other [used for SPA web apps, web APIs] (expose data to XSS)

    • Flow:
    1. user submit login credentials (email + password)
    2. server verifies user input against DB
    3. server generates a temporary token and embeds user data into it
    4. server responses back with token (in body or header)
    5. user stores the token in client storage
    6. user sends cookie with each request
    7. server validate user request & grant access
    8. when user logout, token will be cleared by client storage

Reference: Link

6. Command npx:

The ability of npx is to run the scripts from npm packages without having to install them

7. VSCode Copy && Moving Code Block Hotkeys (Mac users):

shift + option + down key // copying current line of code to next line (handy one)
alt + up / down // moving code up or down

8. Webhook concept:

Explanation: after date, you asked your girlfriend to send you a message once she reached to home. Then, after your girlfriend reached home, then she sends you a message. Then, you feel happy.

Example: Messaging/Notification app: once you sends out some dat via API, then maybe API can tell someone else you have successfully sent the data out, the notification message will be sent after your action is done.

Simple word: you did something, then some other things will be triggered after your action, and also let you know what happened.

9. Redis

It refers to a cache tool which helps developers to save some data as cache so when user refetch the data, user can get it from cache instead of making another API call, eg:

cacheMiddleware() {
  // is a function to save data into redis server for cache purpose
  ...
}
app.get('/path/route', cacheMiddleware, () => { cb ... });

Reference Link

10. How Vue event bus working? An simple example

// Why we need event bus? We want to share the data/props .. between siblings components

// Example Case: we want to share the title between Header and Footer components (siblings)

// Step 1: create event bus instance inside main function
export const bus = new Vue();

// Step 2: using bus and emit event for another component to listen to [For fire the event]
bus.$emit('titleChanged', 'New header title');

// completed version of Header Component:

// <template>
//   <div>
//     <h4 @click="changeTitle">{{ title }}</h4>
//   </div>
// </template>

// <script>
//   import { bus } from '../../main';
//   export default {
//     data() {
//       return {
//         title: 'Header before change'
//       }
//     },
//     methods: {
//       changeTitle: function() {
//         this.title = 'New header title'; // we trigger Header component title update
//         bus.$emit('titleChanged', 'New header title'); // we trigger Footer component title update
//       }
//     }
//   }
// </script>

// Step 3: the component which wants to get the updated data will listen and trigger the changes when another component fired the event bus [For listening the event]
bus.$on('titleChanged', data => {
  this.titleProp = data;
});

// completed version of Footer Component:

// <template>
//   <div>
//     <h4>{{ titleProp || 'default footer content' }}</h4>
//   </div>
// </template>

// <script>
//   import { bus } from '../../main';
//   export default {
//     props: {
//       titleProp: {
//         type: String,
//         required: true
//       }
//     },
//     created() {
//       bus.$on('titleChanged', data => {
//         this.titleProp = data;
//       });
//     }
//   }
// </script>

11. deploy docker container with CI/CD tool (Travis)

create a .travis.yml file and do the following setups:

sudo: required
services:
  - docker

before_install:
  - docker build -t damengrandom/docker-flow -f Dockerfile.dev .

script:
  - docker run damengrandom/docker-flow yarn run test --watchAll=false --coverage

Then connect travis with your github account: read doc and find the related github repository and connect it with Travis (every time commits a new PR, as long as merge into master, the Travis will get triggered to deploy the changes to certain environment)

12. Common regex

// email validator:
function isValidEmail(email) {
   return /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(email);
}

// replace all occurrence in this string
stringTextVariable.replace(/filter/g, '&filter');

// 
var str = "Remove  extra   spaces    inside  string       text          content";
var newStr = str.replace(/\s\s+/g, " ");
console.log(newStr); // "Remove extra spaces inside string text content"

Reference: Link

13. JWT (JSON Web Token)

3 parts: Header, Signature, Payload

Header:

{
  "alg": "HS256", // JWT algorithm
  "typ": "JWT" // JWT type
}

Signature: to verify the message wasn't changed along the way

// If we use SHA256 algorithm, this is how signature looks like:
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

Payload: contains tge data to be sent

{
  name: 'damon',
  handsome: true
}

Good way to integrate is Auth0.

14. tilde (~) vs Caret (^) in npm

~version means: approximately equivalent to version. (update patch version) Eg: ~1.2.3: means will use release from 1.2.3 to <1.3.0

^version means: compatible with version (update minor version) Eg: ^2.3.4: means will use release from 2.3.4 to ❤️.0.0

Good reference here

15. Create VanillaJS Router (Sorry, this is a bad failed example, just another experience of coding Vanilla JS)

<!-- HTML part -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #category ul {
      list-style-type: none;
      display: flex;
    }

    #category ul li {
      flex-grow: 1;
      cursor: pointer;
    }

    .show {
      display: block;
    }

    .hide {
      display: none;
    }
  </style>
</head>
<body>
  <div id="category">
    <ul>
      <li id="pageOne">pageOne</li>
      <li id="pageTwo">pageTwo</li>
      <li id="pageThree">pageThree</li>
    </ul>
  </div>
  <div>
    <div id="pageOneRenderer" class="viewComponent"></div>
    <div id="pageTwoRenderer" class="viewComponent"></div>
    <div id="pageThreeRenderer" class="viewComponent"></div>
    <!-- <div id="errorRenderer" class="viewComponent"></div> -->
  </div>
  <script type="text/javascript" async defer src="main.js"></script>
</body>
</html>
// Javascript part: main.js
const constants = {
  pageOne: [
    {
      id: 1,
      name: 'one 1'
    },
    {
      id: 2,
      name: 'one 2'
    },
    {
      id: 3,
      name: 'one 3'
    }
  ],
  pageTwo: [
    {
      id: 1,
      name: 'two 1'
    },
    {
      id: 2,
      name: 'two 2'
    },
    {
      id: 3,
      name: 'two 3'
    }
  ],
  pageThree: [
    {
      id: 1,
      name: 'three 1'
    },
    {
      id: 2,
      name: 'three 2'
    },
    {
      id: 3,
      name: 'three 3'
    }
  ],
};

const routes = ['pageOne', 'pageTwo', 'pageThree'];

document.getElementById('category').addEventListener('click', (e) => {
  // change url from url bar
  location.href = `${location.origin}${location.pathname}#${e.target.id}`;

  const nodes = document.getElementsByClassName('viewComponent');
  const pathHash = location.hash.substr(1);

  for (let index = 0; index < nodes.length; index++) {
    if (nodes[index].id.includes(pathHash) || location.href.includes(nodes[index].id)) {
      nodes[index].classList.remove('hide');
      nodes[index].classList.add('show');
    } else {
      nodes[index].classList.remove('show');
      nodes[index].classList.add('hide');
    }
  }
});

window.addEventListener('popstate', () => {
  module.renderOnPageLoadOrURLChange();
});

// popstate: is fired when active history entry get changed

window.onload = () => {
  module.renderOnPageLoadOrURLChange(); // get current route page content when page loaded
}

var module = {
  renderSpecificItems: (data, selector) => {
    var div = document.createElement('div');
    div.setAttribute('id', `component-${selector}`);
    
    if (!document.getElementById(`component-${selector}`)) {
      if (typeof data === 'object') {
        data.map(item => {
          var span = document.createElement('span');
          span.innerText = item.name;
          div.appendChild(span);
          div.appendChild(document.createElement('br'));
        });
      } else {
        div.innerHTML = "<p>Default Home Component</p>";
      }
  
      return document.querySelector(`#${selector}`).appendChild(div);
    }
  },
  renderOnPageLoadOrURLChange: () => {
    var currentPath = location.hash.substr(1);

    routes.map(route => currentPath === route ? module.renderSpecificItems(constants[route], `${route}Renderer`) : false);

    // using `map` just one line, using `switch` too many lines, thats the powerful place of using map method, better performance !!

    // switch(currentPath) {
    //   case 'pageOne':
    //     module.renderSpecificItems(constants.pageOne, 'pageOneRenderer');
    //     break;
    //   case 'pageTwo':
    //     module.renderSpecificItems(constants.pageTwo, 'pageTwoRenderer');
    //     break;
    //   case 'pageThree':
    //     module.renderSpecificItems(constants.pageThree, 'pageThreeRenderer');
    //     break;
    //   default:
    //     module.renderSpecificItems(constants.error, 'errorRenderer');
    //     break;
    // }
  }
}

// After few hours coding, just found that I just coded a big tab ...
// I was feeling like SPA is a big tab, each component is the tab content, each link is the tab title !!! 

16. How to delete object from array by using forEach:

// data to use
var data = [{x: 1, y: 2}, {a: 1, b: 2}, {special: 'hahaha'}];
// functionality
data.forEach(val => {
  if(val.special === 'hahaha') {
    const valIndex = data.indexOf(val);
    if(valIndex > -1) {
      data.splice(valIndex, 1);
    }
  }
});
// output:
data; // [{x: 1, y: 2}, {a: 1, b: 2}]

17.axios.create()

The axios.create() function creates a new Axios instance. When you require('axios'), you get back an the default Axios instance. The reason why you would create an instance is to set custom defaults for your application.

18. MicroServices

What is MicroServices: Divide one monolithic codebase into multiple services codebase:

One to many -> which means one service can have one UI + one API + one DB (database per services - DPS) !!

19. Loop until condition reaches

const fn = () => {
  let rand = 0;
  
  while (true) {
    rand = Math.floor(Math.random() * 90 + 10);
    console.log(rand);
    if (rand === 12) {            
      break;
    }
  }
}

fn();

20. Personal Dignity Note

console.clear();

const stores = [
  {
    items: ["apple", "banana", "flour", "salt"]
  },
  {
    items: ["flour", "salt", "sugar"]
  },
  {
    items: ["apple", "apple", "flour", "lemon", "salt", "sugar"]
  }
];

console.log("hello");

// my code: during live coding test

function getFirstFindResult(keyword) {
  let keywordFoundArray = [];

  for (var i = 0; i < stores.length; i++) {
    for (var j = 0; j < stores[i].items.length; j++) {
      for (var k = 0; k < keyword.length; k++) {
        if (stores[i].items[j] === keyword[k]) {
          keywordFoundArray.push(keyword[k]);
        }

        if (keywordFoundArray.length === keyword.length) {
          return stores[i].items;
        }
      }
    }
  }
}

console.log(getFirstFindResult(["flour", "salt"]));
console.clear();

const stores = [
  {
    items: ["apple", "banana", "flour", "salt"]
  },
  {
    items: ["flour", "salt", "sugar"]
  },
  {
    items: ["apple", "apple", "flour", "lemon", "salt", "sugar"]
  }
];

console.log("hello");

// my code: after one day I started for dignity fight

function getFirstElement(paramsArray) {
  return stores.map(store => {
    if (store.items.join().includes(paramsArray.join())){
      return store.items;
    }

    return false;
  })[0];
}

console.log(getFirstElement(["flour", "salt"]));

21. Why using webpack instead of put script tag inside html file?

Reason: Webpack make all the script files finally compiled as 1 bundle file, something like this:

<script src="jquery.js" type="text/javascript"></script>
<script src="app.js" type="text/javascript"></script>
// without implementation (just put into html file)

becomes to

<script src="bundle.js" type="text/javascript"></script>
// with webpack implementation

Advantage of using webpack instead of import inside html file is we have ability to set the environment variable to control whether shall we load this file as part of bundle.js or not !!!

something like this:

let pluginPartial = "";

if (appcuesEnabled) {
  pluginPartial += fs.readFileSync(path.resolve(__dirname, `./src/partials/appcues.html`), "utf8");
}
// include html inside `HtmlWebpackPlugin` plugin
new HtmlWebpackPlugin({
  title: "Bundle HTML files together",
  template: "index.html",
  plugin: pluginPartial,
}),

// inside `./src/partials/appcues.html` file, we have:
<script src="//fast.appcues.com/specific_id.js"></script>