Monday, 25 October 2021

Javascript cheat sheet

Promise

The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.

Therefore we can let an asynchronous method to return as a synchronous method. We can associate handlers to the promise. These handlers will handle eventaul success values or failure reason.

A promise has three states: pending, fulfilled with a value or rejected with a reason. We use then method of promise object to attach handler.

Consuming promise

promiseObj.then(successCallBackFunc, failureCallbackFunc)

Guarantees for then()

  1. then will never be invoked if promise is in pending state
  2. then will be called event if it is added after promise has exited from pending state
  3. can add multiple then. These thens will be called in the order they are added

promise.catch()

return a promise and deals with rejected case only. It is the same as to call then(undefined, onRejected)

promise.finally()

  • the finally() method is executed when the promise is settled no matter it is successful or failed
  • This handler of finally receives no parameters
  • It will return another promise

Creating Promise

Promise.resolve(value) will return

  1. A promise that is resolved by value passed as argument
  2. If value passed as argument is a promise, will return that promise

Promise.reject(reason) will return A promise object that is rejected with a given reason

Promise.all() The argument of all is an array of promise. It will return one promise. This returned promise fulfills when all of the input's promises fulfill (including when an empty iterable is passed), with an array of the fulfillment values. It rejects when any of the input's promises rejects, with this first rejection reason.

The Promise.race() static method takes an iterable of promises as input and returns a single Promise. This returned promise settles with the eventual state of the first promise

setTimeout(functionRef, delay, param1)  delay unit is millisecond
const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, 'tuttle');
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'rabit');
});

Promise.race([promise1, promise2]).then((value) => {
  console.log(value);
  // Both resolve, but promise2 is faster
});
// Expected output: "rabit"
//Promise in action
//Promise constructor accepts two predefined 
//functions: resolve and reject
let p = new Promise((resolve, reject)=> {
        let good = false
        if (good) {
                resolve(100)
        } else {
                reject("sad. bad")
        }
});

//we will see sad. bad. However, if we set good to be true,
//will see 101. Here then accepts two functions. The first is
//for fulfillment and the second is for rejection
p.then((n)=> console.log(n+1), (msg)=>console.log(msg))

//here is another way
p.then((n)=> {
    console.log("resolved")
    console.log("n", n+1)
}).catch((msg) => {
    console.log("rejected")
    console.log("msg", msg)
})

Put axios in a Promise chain

//sample codes to put axios in a Promise chain
session.onpaymentauthorized =  (event)=> {
    applePayInstance.tokenize({
        token: event.payment.token
    }).then( (payload) => {
        const requestData = {
            url: '/test/do-whatever/',
            method: 'post',
            headers: {'content-type': 'application/x-www-form-urlencoded'},
            data: "amount=111"
        }
         
         //return another promise and it will be put in this chain
         return axios(requestData)
    }).then(response => {
            if (response.data.success){
                console.log("good. will complete sesson to dismiss sheet")
            } else {
               console.log("creating order failed")
            }
    }).catch((tokenizeErr) => {
        console.log('Error tokenizing Apple Pay:', tokenizeErr);
        session.completePayment(ApplePaySession.STATUS_FAILURE);
    });
};
//an example to use axios
//an example to use axios
import axios from "axios";
let postData = {
    name: "john",
    age: 35,
};

const requestData = {
    url: '/myulr/test/?eventName=' + eventName,
    method: 'post',
    headers: {
        'content-type': 'application/json',
        'x-requested-with': 'XMLHttpRequest'
    },
    data: postData
}

axios(requestData)
//server side to invoke by node.js
const axios = require('axios');

//to debug
axios(requestData).catch((err) => {
    console.log(err.response)
})

Use async function to handle promise

An async function is a function declared with the async keyword. It works with await keywords to handle promise in a cleaner style. Await and async will not block javascript main thread. await will wait a result of a promise. Here is an example:

myPromiseGenerator = function() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('Hello world');
    }, 2000);
  });
}

async function myFunc() {
  console.log('calling');
  
  //waiting for promise result
  const result = await myPromiseGenerator();
  console.log(result);
}

myFunc()

//output will be the following
//calling
//Hello world

Object.assign

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(target);
// Expected output: Object { a: 1, b: 4, c: 5 }

console.log(returnedTarget)
// Expected output: Object { a: 1, b: 4, c: 5 }

console.log(source)
// Expected output: Object { a: 1, b: 2} . no change from origin

for ..of loops

ES6 adds a for ..of loop. It is used to loop of set of values produced by an iterator. Most likely, will be used to loop through array and string


var arr = ['a','b','c']
for (var val of arr) {
    console.log(val)
}
//'a', 'b', 'c'


for (var c of 'hi') {
    console.log(c)
}
//'h', 'i'

//loop array index
for (let i in arr) {
    console.log(i)
}
//0,1,2

use object as hash table

The below is a solution for a LeetCode problem


/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
	//define a object
    let d = {}
    
    for (let n of nums) {
    	//check if n is a property of object. like check if hash has key
        if (n in d) {
            d[n] = 2
        } else {
            d[n] =1
        }
    }
    
    //loop through object's property
    for (let n in d) {
        if (d[n]==1) {
            return n;
        }
    }
    
    //if want to get all properties of this object
    let keys = Object.keys(d)
    
    // get length
    Object.keys(obj).length
};

Build array of objects

//build offer array
let offerVals = []
for (let offer of data.offers) {
    let obj = {}
    obj[offer.sku] = offer.quantity
    offerVals.push(obj)
}
//build json string with array. noted that build obj in two ways
//output {"category":"developers","persons":[{"name":"leo","age":50},
//{"name":"john","age":40}]}
let obj = [];
obj.push({ name: "leo", age: 50 });

let p2 = {};
p2["name"] = "john";
p2["age"] = 50;
obj.push(p2);

let str = { category: "developers", persons: obj };
console.log(JSON.stringify(str));

ES6 template literals

Use backtick ` as delimiter.

let name="leo"
let welcome = `hi ${name}!`;

console.log(welcome) //hi leo!

//allow split across multiple lines
let name=`hello
world`;

//hello
//world
console.log(name)

Array

//sort number array
nums.sort((a,b)=>a-b)

//initiate array with single values
// arr = Array(arraySize).fill(value)
let ans = Array(5).fill(-1)

//copy array
const animals = ['dog', 'bison', 'camel', 'duck', 'elephant'];

let animalCopy = animals.slice();

//also can do the following to copy
let animalCopy = [].concat(animals)


//array merge
const array1 = ['a', 'b', 'c'];
const array2 = ['d', 'e', 'f'];
const arr3 = ['j','p']
const array4 = array1.concat(array2, arr3);
//array4 is ['a', 'b', 'c','d', 'e', 'f','j','p']

//unshift to add element in the begining of array
const array1 = [1, 2, 3];
array1.unshift(4, 5);
console.log(array1);
// expected output: Array [4, 5, 1, 2, 3]

//map() will create a new array by calling a provided function for every elements
const arr1 = [1, 2, 3]
const arr2 = arr1.map((n)=>n*n)
console.log(arr2) //[1,4,9]

//use filter to move element to the begin of array. Here assume p is in array and it is unique
 arr = arr.filter(item => item !== q);
 arr.unshift(q);
 
 //create a 26 letters array
 const letters = 'abcdefghijklmnopqrstuvwxyz'.split('');
 
 //string to array
 let s ="leetcode"
 const chars = [...s];

Object destructuring

const pet = {name:"weiwei", age:13}

//here is object destructuring
 const {name, age} = pet
 
 console.log("name", name)
 console.log("age", age)
 
 //Destruct and Rename
const person =  {
    name: "leo",
    country: "Canada"
}

const {name:first} = person
console.log("first is:", first) //leo
console.log("name:", name) //undefined

Math


// integer division. will get 4
Math.trunc(32/7)

High order component

A good blog about high order component

Four steps

  1. Create a base component
  2. Create a function which take base component and return a upgraded component
  3. import that function and call it to get a new component
  4. use this new component. This new component normally has new extra props

Redux form is high order component. Here is a good introduction for redux form.

Response.json()

The json() method takes a Response stream and reads it to completion. It returns a promise which resolves with the result of parsing the body text as JSON. Then we can use this data to do some thing. The pattern is showing below which work with fetch.

const remoteEndPoint = "https://someapi";
fetch(remoteEndPoint)
      .then((response) => response.json())
      .then((data) => {
        this.setState({ loading: false, data: data });
      })
      .catch(console.error);

Use Axios

We can send a header config when do API call using Axios. Noted position of config field for get and post are different.

const config = {
    headers: {
        "X-Authorization-JWT": initData.jwt,
        "Content-Type": "application/json"
    }
}

axios.get(url, config)
axios.post(url, data, config)
axios.put(url, data, config)

//to pass csrf and more headers
const config = {
    headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': csrf
    }
}

lodash

_.includes( collection, value)

let a=[1,2]
let f = _.includes(a, 3) //false
f = _.includes(a,1) //true 

Some useful built in function

slice() will do a shallow copy of an array. You can pass indexes as argument of the function. If no argument is passed, do a shallow copy of entire array

const animals = ['ant', 'bison', 'elephant', 'dog'];
console.log(animals.slice());
// expected output: Array ["ant", "bison", "elephant", "dog"]

Object.assign() method copies all enumerable own properties from one or more source objects to a target object. It returns the modified target object.

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source, {leo:22});
console.log(target);
console.log(returnedTarget);
//output
> Object { a: 1, b: 4, c: 5, leo: 22 }
> Object { a: 1, b: 4, c: 5, leo: 22 }

two ways to copy an object

var player = {score: 1, name: 'Jeff'};
var newPlayer = Object.assign({}, player, {score: 2});
// Now player is unchanged, but newPlayer is {score: 2, name: 'Jeff'}

// Or if you are using object spread syntax proposal, you can write:
// var newPlayer = {...player, score: 2};

Array reduce(). It accept a callback, and will work on every element in order. After done, return the last value. For that callback function, the first argument is the previous value, and the seconde is the current value. When run on the first element, we can pass an initial value

let arr=[1,2,3]
let iniV = 7
let ans = arr.reduce((total,n)=>total*n, 7)
console.log(ans) //42 = 7*1*2*3

If initial value is not provided, the first element will be used as init value and process element starting from the second element.

let arr=[1,2,3]
let ans = arr.reduce((total,n)=>total*n)
console.log(ans)//6=1*2*3

mapping letter to integer. 'A' =>1 A has value 65

columnTitle.charCodeAt(i)-64

cast type

let a="8"
let b = +a
console.log(typeof a) //string
console.log(typeof b) //number

Optional chaining (?.)

In most use case, try to access an property of object. If it does not exist, return undefined instead of giving out error.

const obj = {
  cat: {
    name: 'Dinah'
  }
};

console.log(obj.cat2?.name);
// expected output: undefined

console.log(obj.cat2.name);
//expected error

console.log(obj.cat.name);
//Dinah

Use [key] notation for object

const name = "leo"
const obj = {[name]:"developer"}

console.log(obj.leo)
console.log(obj[name])

//undefined
console.log(obj.name)

char, int, ascii code

//solution for Leetcode 2194
var cellsInRange = function(s) {
    let c1 = s.charCodeAt(0)
    let c2 = s.charCodeAt(3)
    
    //0 ascii code is 48
    let r1 = s.charCodeAt(1) - 48
    let r2 = s.charCodeAt(4) -48
    
    let ans = []
    
    for (let c=c1; c<=c2; c++) {
        for (let r=r1; r<=r2; r++) {
        	//ascii code to char
            let cell = String.fromCharCode(c) + r
            ans.push(cell)
        }
    }
      
    return ans
    
};

Logic or

//The Logical OR operator (||) returns the value of its 
//second operand, if the first one is falsy, otherwise the value
//of the first operand is returned
let a ="foo" || "bar"; // returns "foo"
console.log(a)

a = false || "bar"; // returns "bar"
console.log(a)

window.dataLayer = window.dataLayer || [];

Class

Solution for Leetcode 2622

var TimeLimitedCache = function () {
  this.d = {};
};

/**
 * @param {number} key
 * @param {number} value
 * @param {number} time until expiration in ms
 * @return {boolean} if un-expired key already existed
 */
TimeLimitedCache.prototype.set = function (key, value, duration) {
  let ans = false;
  if (key in this.d) {
    let obj = this.d[key];
    if (obj.expiry >= Date.now()) ans = true;
  }
  this.d[key] = { v: value, expiry: duration + Date.now() };

  return ans;
};

/**
 * @param {number} key
 * @return {number} value associated with key
 */
TimeLimitedCache.prototype.get = function (key) {
  if (key in this.d) {
    let obj = this.d[key];
    return (obj.expiry >= Date.now()) ? obj.v : -1
  }

  return -1;
};

/**
 * @return {number} count of non-expired keys
 */
TimeLimitedCache.prototype.count = function () {
  let ans = 0;
  let keys = Object.keys(this.d);
  for (let k of keys) {
    if (this.d[k].expiry >= Date.now()) ans = ans + 1;
  }
  return ans;
};

/**
 * Your TimeLimitedCache object will be instantiated and called as such:
 * var obj = new TimeLimitedCache()
 * obj.set(1, 42, 1000); // false
 * obj.get(1) // 42
 * obj.count() // 1
 */

Solution for Leetcode 2695

/**
 * @param {number[]} nums
 */
var ArrayWrapper = function(nums) {
    this.nums = nums
};

ArrayWrapper.prototype.valueOf = function() {
    return this.nums.reduce((a, b) => a + b, 0)
}

ArrayWrapper.prototype.toString = function() {
    return `[${this.nums.join()}]`
}

/**
 * const obj1 = new ArrayWrapper([1,2]);
 * const obj2 = new ArrayWrapper([3,4]);
 * obj1 + obj2; // 10
 * String(obj1); // "[1,2]"
 * String(obj2); // "[3,4]"
 */

Some mistakes

The below is solution for Leetcode 2627

Scope problem. use pendingF = [] instead of let pendingF = []. Without let, pendingF becomes a global variable. Because Leetcode will run bunches of test, pendingF is accessed by all tests and it causes a hard fix bug.

/**
 * @param {Function} fn
 * @param {number} t milliseconds
 * @return {Function}
 */
var debounce = function (fn, t) {
  //make sure this variable is not global. Need let
  let pendingF = [];
  return function (...args) {
    let cur = Date.now();
    for (let obj of pendingF) {
      if (obj.start > cur) {
        clearTimeout(obj.timeout);
      }
    }

    myTimeout = setTimeout(() => fn(...args), t);
    pendingF.push({ timeout: myTimeout, start: cur + t });
  };
};

/**
 * const log = debounce(console.log, 100);
 * log('Hello'); // cancelled
 * log('Hello'); // cancelled
 * log('Hello'); // Logged at t=100ms
 */

Sort Array

Sort Array

Play with object

/**
 * @param {Object} obj
 * @return {Object}
 * Leetcode 2822
 */
var invertObject = function (obj) {
  let ans = {};
  for (let k of Object.keys(obj)) {
    let v = obj[k];

    if (Object.hasOwn(ans, v)) {
      let cur = ans[v];

      if (Array.isArray(cur)) {
        cur.push(k);
      } else {
        cur = [cur];
        cur.push(k);
      }

      ans[v] = cur;
    } else {
      ans[v] = k;
    }
  }

  return ans;
};

Set

let set = new Set();
set.add(1);
set.add(1);
set.add(2);
set.add(100);

//size is 3
console.log(set.size);

Debug

Safari

  • right click page. select inspect element to show console
  • click recycle bin in the upper right corner to clear console

Chrome

  • right click page. select inspect to show console
  • type console.clear() to clear console

package.json

//do not install devDependencies
npm install --production

//will install devDependencies
npm install

jQuery

//ajax call to get data
$.get("http://test.com", function(data, status){
    alert("Data: " + data + "\nStatus: " + status);
});
//find first element of a class
$(".myClass").first();
//pass a string containing HTML and create a new element:
let html = "
Hi
"; let myEle = $(html);

let parent = $(".myClass").first();
let html = "<div>Hi</div>";
let myEle = $(html);

parent.append(myEle);

Switch node version by nvm

nvm list

# add the following in .bashrc, so alway use the version 16 when open a terminal
nvm use 16.15.1

not null and not undefined

//the followinig two lines are equasl
a != null;
a !==null && a !== undefined;














No comments:

Post a Comment