Understanding the JavaScript Event Loop

JavaScript is a single-threaded language, which means that it can only do one thing at a time. However, it is still able to handle multiple tasks at once through the use of the event loop.

The event loop is a mechanism that allows JavaScript to run asynchronous code while still processing other code. It works by constantly checking the call stack for any pending function calls, and then executing them one by one. If a function call takes too long to complete, it gets deferred to the back of the queue and is processed later.

Browser Important Concepts

The entire runtime environment of a browser is not composed solely of the JavaScript engine. Because the language features of JS belong to a single thread, but in order to allow web pages to have functions similar to “listening for events”, “timing”, and “pulling third-party APIs”, the browser provides other parts to achieve these functions, which are:

  • Event Queue
  • Web API
  • Event Table
  • Event Loop

For the browser’s runtime environment, there are other important components in addition to the JavaScript engine, and these components work together to enable the browser to provide rich functionality and handle multiple tasks.

Among them, Event Queue, Web API, Event Table, and Event Loop are important components in the browser that can work together to handle asynchronous operations and event handlers.

Event Queue
The Event Queue is a FIFO data structure that stores events waiting to be processed. When an event occurs, it is added to the event queue and waits for processing. The event queue can store various events, such as user operation responses, timer events, network requests, and more.

Web API
Web API is a set of APIs provided by the browser for handling asynchronous operations, such as network requests, timers, local storage, and more. Web APIs are usually implemented in native code provided by the browser and are separate from the JavaScript engine. This means that when we call a Web API, the JavaScript engine delegates the task to the Web API and returns immediately without waiting for the task to complete.

Event Table
The Event Table is a data structure that stores event handlers. When an event occurs, the browser looks up the event table to determine which event handlers should be executed. The event table is usually implemented in native code provided by the browser.

Event Loop
The event loop is an infinite loop that listens to the event queue and calls the corresponding event handler. When there are events in the event queue, the event loop retrieves them and calls the corresponding event handler. The main function of the event loop is to ensure that the JavaScript engine can keep running when handling asynchronous operations, without blocking other operations in the browser.

The Call Stack

The call stack is a data structure that keeps track of the functions that are currently being executed. Whenever a function is called, it is added to the top of the call stack. When the function completes, it is removed from the stack, and the next function in line is executed.

1
2
3
4
5
6
7
8
9
10
11
function multiply(a, b) {
return a * b;
}

function add(a, b) {
let result = a + b;
result = multiply(result, result);
return result;
}

console.log(add(2, 3)); // output: 25

In the code above, the add function calls the multiply function, which in turn returns a value that is used in the add function. The call stack keeps track of the order of execution and ensures that the code runs in the correct order.

Asynchronous Code

Asynchronous code is code that runs outside of the normal call stack. This can include things like user input, network requests, and timers. When asynchronous code is executed, it is added to a separate queue known as the event queue.

1
2
3
4
5
6
7
console.log('Start');

setTimeout(() => {
console.log('Timeout');
}, 0);

console.log('End');

In the code above, the setTimeout function is used to create a timer that will run after 0 milliseconds. Despite the short delay, the function is not executed immediately. Instead, it is added to the event queue and will be executed once the call stack is empty.

The Event Loop

The event loop is responsible for monitoring both the call stack and the event queue. When the call stack is empty, the event loop takes the first function in the event queue and adds it to the call stack. This function is then executed, and any resulting functions are added to the back of the event queue.

1
2
3
4
5
6
7
8
9
10
11
console.log('Start');

setTimeout(() => {
console.log('Timeout');
}, 0);

Promise.resolve().then(() => {
console.log('Promise');
});

console.log('End');

In the code above, a Promise is used to create another asynchronous task. Despite being created after the setTimeout function, the Promise is executed first because it is added to the microtask queue, which has a higher priority than the event queue.

Conclusion

The JavaScript event loop is a powerful mechanism that allows asynchronous code to be executed without blocking the main thread. By understanding how the call stack, event queue, and event loop work together, you can write more efficient and responsive code. Remember to use asynchronous code whenever possible, and always be mindful of how your code will affect the event loop.

Java Concurrent basic notes

In Java, “async” and “sync” refer to different ways of executing code and handling concurrency.

Synchronous code is executed in a single thread, with each statement being executed in sequence. When a statement is executed, the program waits for it to finish before moving on to the next statement. This can be useful when you need to ensure that certain code is executed in a specific order, but it can be inefficient if the code is doing something that takes a long time to complete, as the program will be blocked until the code finishes.

Asynchronous code, on the other hand, allows multiple tasks to be executed at the same time. Instead of waiting for a task to finish before moving on to the next one, asynchronous code can start a task and then move on to the next one, while the first task is still running in the background. This can be much more efficient, as the program can continue doing other things while waiting for long-running tasks to complete.

In Java, you can write asynchronous code using the CompletableFuture class, which provides a way to execute tasks in the background and then handle the results when they are ready. CompletableFuture allows you to chain together multiple tasks and specify how they should be executed, such as in sequence or in parallel.

To summarize, synchronous code executes one statement at a time in sequence, while asynchronous code allows multiple tasks to be executed in parallel, improving performance and efficiency.

CompletableFuture is a class introduced in Java 8 that provides a way to write asynchronous, non-blocking code. It is a powerful tool for handling complex asynchronous operations in a clear and concise manner.

CompletableFuture is a type of Future that represents a computation that may or may not have completed yet. It can be used to execute a task in the background and then handle the result when it becomes available, or to execute multiple tasks concurrently and then combine the results when they are all ready.

Here are some of the key features of CompletableFuture:

  1. Chaining: CompletableFuture allows you to chain together multiple asynchronous operations, so that one operation starts when the previous one finishes. This can be done using methods like thenApply(), thenCompose(), and thenCombine().

  2. Combining: CompletableFuture also allows you to combine multiple asynchronous operations into a single operation, using methods like allOf() and anyOf().

  3. Error handling: CompletableFuture provides methods for handling errors that may occur during the execution of an asynchronous operation, including exceptionally() and handle().

  4. Timeout handling: CompletableFuture allows you to set a timeout for an asynchronous operation, using methods like completeOnTimeout() and orTimeout().

  5. Asynchronous execution: CompletableFuture can execute tasks asynchronously on a separate thread, allowing the calling thread to continue with other tasks while the background task is executing.

  6. Completion stages: CompletableFuture provides a way to break down complex asynchronous operations into smaller, more manageable stages, using methods like thenApplyAsync(), thenComposeAsync(), and thenAcceptAsync().

Overall, CompletableFuture provides a flexible and powerful way to write non-blocking, asynchronous code in Java, making it easier to handle complex operations and improve performance.

Spring Basic Notes 1

To talk about the history of Spring, we need to talk about J2EE. The widespread implementation of J2EE applications started in 1999 and 2000, bringing standardization of core middle-tier concepts such as transaction management, but it was not an absolute success in practice, as development efficiency, development difficulty and actual performance were disappointing.

Anyone who has ever used EJB to develop a JAVA EE application like me must know that learning and applying EJB is very hard at the beginning and many things are not easy to understand at once. The configuration is also complex and monotonous, and the code for object lookup using JNDI is also monotonous and boring. The high cost of learning EJB, and very low development efficiency, very high resource consumption, have caused the use of EJB difficulties. And Spring emerged initially to solve these problems like these.

One of the biggest purposes of Spring is to make Java EE development easier. Much more easier.

Core Container

Spring’s core container is the foundation on which other modules are built, consisting of

  • Beans module,
  • Core module
  • Context context module
  • The SpEL expression language module

Without these core containers, it is also impossible to have AOP, Web, and other upper layer features.

AOP module

It provides a aspect-oriented programming implementation, which provides functions such as logging, permission control, performance statistics, and other general functions that separated from business logic , and can dynamically add these functions to the required code, so that each has its own role to reduce the coupling of business logic and general functions

很多开发者入门都是从Spring Boot开始的,他对Spring整体框架底层,以及发展历史不是很了解; 特别是对于一些老旧项目维护和底层bug分析没有全局观。
Many developers start with Spring Boot, he does not have a good understanding of the overall framework underlying Spring, and the development history; especially for some older projects maintenance and underlying bug analysis does not have a global view.
Spring represents a framework design philosophy that requires a global understanding of how Spring Framework components work together and the need to understand the original intent of its design and future trends.

Spring框架管理这些Bean的创建工作,即由用户管理Bean转变为框架管理Bean,这个就叫控制反转 - Inversion of Control (IoC)Spring
框架托管创建的Bean放在哪里呢? 这便是IoC Container;Spring 框架为了更好让用户配置Bean,必然会引入不同方式来配置Bean? 这便是xml配置,Java配置,注解配置等支持Spring
框架既然接管了Bean的生成,必然需要管理整个Bean的生命周期等;
应用程序代码从Ioc Container中获取依赖的Bean,注入到应用程序中,这个过程叫 依赖注入(Dependency Injection,DI) ; 所以说控制反转是通过依赖注入实现的,其实它们是同一个概念的不同角度描述。通俗来说就是IoC是设计思想,DI是实现方式在依赖注入时,有哪些方式呢?这就是构造器方式,@Autowired, @Resource, @Qualifier… 同时Bean之间存在依赖(可能存在先后顺序问题,以及循环依赖问题等)

Updating my hexo and icarus install

Updating Hexo Install

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
npm install -g hexo-cli
hexo version

npm install -g npm-check
npm-check

npm install -g npm-upgrade
npm-upgrade

npm update -g
npm install -g npm

hexo clean
hexo g -s
hexo d

Updating hexo theme

  1. Remove node_modules folder
  2. remove "hexo-theme-icarus": "^5.1.0" in package.json
1
2
3
4
5
npm install
npm install [email protected]
npm install hexo-renderer-inferno
hexo config theme icarus
hexo server

use the original icarus config

Password store paradigm

The very first thing

We should always remind ourself is that, we should not store passwords yourself. At least, we should try out best to avoid it.

As a User

Password manager and 2FA is strongly suggested. However, it is not the thing I want to discuss today.

As a develop

As a developer, we are unavoidably need to store user’s password.

Storing in plain text

The most naive way is to store user’s password in plain text. Once the database is leaked or have insider, all user’s password is leaked. Sadly, many people in the world are using the same username and password in different website. And thats why we should use password manager as a user.

Encrypt the password

It is a little bit better than store it as plain text. However, it still incredibly easy to get things wrong. Imagine that the database is leaked therefore Hacker have the whole database offline. They can see the encrypted code aka the ciphertext. Under lots of encryption algorithm, same text will generate same ciphertext. If it is a very large database, it most likely have many same password (especially for some easy, common passwords). The scariest part is that, some times the reset password system may also store “hints” of the password. Imagine there are 20 same encrypted password, that means I will have 20 different hints point to a same password.

Hashing (without salts)

hash(m)

Hashing and store the hashed password almost get the things right. However, it still can go wrong with some old hashing algorithm. let me introduce a idea, rainbow table: pre-computed hash chains. Improve on the dictionary attack to trade time for space. It is a common and strong approach to crack hash nowadays. By matching the hashed cipher text and rainbow table, hacker can easily find some of the correct match of password. If the database is compromised. Although it is the intruder who gets the hash value, it is also easy to restore the password plaintext in bulk due to the existence of rainbow tables.

Hashing (with salts)

The rainbow table is generated for a specific function H. If H changes, the existing rainbow table data is completely unusable. If using salt value, then a different rainbow table must be generated for each user. It greatly increases the difficulty of cracking. And the best practice is to use a different salt for each user since it is worth mentioning that, the tensor computing provided by display card to highly speed up the hack cask. Which make it even more danger now and in the future.

A practices that I have implement is make use of the fact that username is usually cannot change. Use username for as the salt.

Upgrading the old method from the past

It is common that we need to upgrade the hashing algorithm form the past but at the same time do not want to affect the user. For plain text, it just need to hash the password. And so is the encryption, it is just need to decrypt the password before hashing.

What if we already have hashed password? The fact that we cannot restore the password because hashing is a many-to-one compression. The solution is salt and pepper.

  • m: message, password in this case
  • h1: the outdated hash algorithm
  • h2: the modern hash algorithm
  • salt: salt is not secret (merely unique) and can be stored alongside the hashed output
  • pepper: pepper is secret and must not be stored with the output.

h2(h1(m)+pepper) , salt is optional in this case. the h1 might have salted already.

hash(m+salt)
it must be safe to ensure that each user’s salt is different.

Setup mysql with docker

The docker compose file I use:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
version: '3'

services:
mysql:
image: mysql/mysql-server
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: <mypw>
MYSQL_DATABASE: app_db
MYSQL_USER: dev
MYSQL_PASSWORD: <mypw>
ports:
- "3306:3306"
volumes:
- ./data:/var/lib/mysql
phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: pma
links:
- mysql
environment:
PMA_HOST: mysql
PMA_PORT: 3306
PMA_ARBITRARY: 1
restart: always
ports:
- 8081:80

Access into the docker container

docker exec -it <container id> bash

The container id can be find by docker ps

Create new database

mysql -u root -p

CREATE DATABASE 'newdatabase';

1
2
3
4
CREATE USER 'dev'@'localhost' IDENTIFIED BY 'mypw';
CREATE USER 'dev'@'%' IDENTIFIED BY 'mypw';
GRANT ALL ON *.* TO 'dev'@'localhost';
GRANT ALL ON *.* TO 'dev'@'%';

flush privileges;

CREATE USER 'newuser'@'%' IDENTIFIED BY 'newpassword';

Then give the new account “newuser” permission to read and write the new database

GRANT ALL PRIVILEGES ON newdatabase.* TO 'newuser'@'localhost';

quit the root login and switch to the user

quit

mysql -u <newuser> -p

How to build a hello world docker image by docker file

First, create a `hello-world.js’ file

1
console.log("Hello World")

Then, create a Dockerfile in the same directory, the Dockerfile should look like that:

1
2
3
4
5
6
7
8
9
10
FROM ubuntu

RUN apt update && apt install nodejs -y

WORKDIR /app

COPY . .

CMD ["node", "/app/hello-would.js"]

FROM ubuntu means we ubuntu the ubuntu image as the base

RUN apt update && apt install nodejs -y means install nodejs into the ubuntu image

WORKDIR is used to define the working directory of a Docker container.

COPY . . is to copy the current directory(the hello-world.js) to the WORKDIR

CMD ["node", "/app/hello-would.js"] is the command to run after the image load.

Finally, Build the image

docker build -t {image name and version} .

-t is the tag for the image name and version, for example, etklam/hello_app:0.1

. is the Dockerfile directory

MYSQL | what's the different betweenUTF8 and UTF8-mb4

Main different

The main different between utf8 and utf8-mb4 is utf8 is only 3 bytes but utf8-mb4 is 4bytes instead. Note that UTF8 have 4 bytes, utf8mb4 is the true utf8 character set.

In general, it is enough to use MySQL utf8 to set up a website, however, Some special (Chinese) characters or common emoji are not included in 3 bytes. Therefore, most Chinese characters are sufficient, but they cannot be used for all characters. If you want to use special characters or emoticons, you cannot use MySQL’s utf8 character set to store them.

UTF8 to UTF8mb4 does not cause incompatibility problems.

Notes about ajax request

Create XMLHttpRequest object

XMLHttpRequest is basic of Ajax request,

1
const xhr = new XMLHttpRequest();

Send a request to the server

1
2
xmlhttp.open("GET", "url"); // url is the api endpoint
xml.send();

onreadystatechange

There are 5 state of xmlhttprequest, from 0 to 4

  1. Request not initialized
  2. Server connection is established
  3. Request has been received
  4. Request is being processed
  5. Request completed and response is ready

Hence, When readyState is equal to 4 and the status is 200, the response is ready.

1
2
3
4
5
xml.onreadystatechange=function() {
if(xml.readyState==4 && xml.status==200) {
document.getElementById("myDiv").innerHTML=xml.responseText;
}
}

Ajax json examples

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function loadXMLDoc(){
// init a xmlhttprequest
const xmlhttp = new XMLHttpRequest();

// init a onreadystatechange and parse xml to json
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
var myArr = JSON.parse(this.responseText);
myFunction(myArr)
}
}
//send the xml request
xmlhttp.open("GET","/try/ajax/json_ajax.json",true);
xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xmlhttp.send();
}
// function to change the dom
function myFunction(arr) {
var out = "";
var i;
for(i = 0; i < arr.length; i++) {
out += '<a href="' + arr[i].url + '">' +
arr[i].title + '</a><br>';
}
document.getElementById("myDiv").innerHTML=out;
}

Ajax with Promise examples

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

const p = new Promise((resolve, reject)=>{
const xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4){
if (xmlhttp.status==200)
{
//success
resolve(this.responseText)
}else{
//fail
reject(xmlhttp.status)
}
}
}
})

//promise followup
const result = p.then(function(value){
let myArr = JSON.parse(value)
myFunction(myArr)
return myArr
},function(reason){
console.log(reason)
return 'error'
})

// function to change the dom
function myFunction(arr) {
var out = "";
var i;
for(i = 0; i < arr.length; i++) {
out += '<a href="' + arr[i].url + '">' +
arr[i].title + '</a><br>';
}
document.getElementById("myDiv").innerHTML=out;
}

Learn Spring Boot 1

Spring initialization

  • spring-boot-starter-web
  • spring-boot-starter-data-jpa
  • spring-boot-devtools
  • mysql-connector-java
  • lombok

Connect to database

in the resource/application.properties, we can config the hibernate connection for mysql

1
2
3
4
5
6
spring.jpa.hibernate.ddl-auto=create-drop
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.show-sql= true

Simple API

To build a simple api, we need to add two annotaion to the main

  • RestController
  • @GetMapping/@PostMapping/ others
1
2
3
4
5
6
7
8
9
10
11
12
13
@SpringBootApplication
@RestController
public class PpfaSpringApplication {

public static void main(String[] args) {
SpringApplication.run(PpfaSpringApplication.class, args);
}

@GetMapping
public String hello() {
return "Hello World";
}
}