JavaScript and What You Need to Know (Part 1)
JavaScript is a language that is all too familiar to us. In this article, I will not give the theory for example what javaScript is bla bla .. (if you want to read this, you can google the mountain.) I just write briefly what you need to know about JavaScript based on my own experience and define it in “my popular language”.. JavaScript can not only do on Frontend (some popular frontend frameworks today: ReactJS, VueJS, …) but also Backend (Nodejs). You see JavaScript is beneficial, right Below I will list some of the concepts that a JavaScript person needs to understand and understand. Let’s go
1. What is Synchronous and Asynchronous (Asynchronous)?
- Synchronous : ie you have 3 jobs “Brushing”, “Breakfast”, “Going to school”. When you finish “Brushing your teeth”, you can go to work “Breakfast”, and you have to finish “Breakfast” before you start “Going to school”. To map with code in JavaScript, I have the following code:
1 2 3 4 | console.log("Đánh răng"); console.log("Ăn sáng"); console.log("Đi học"); |
Results returned in the correct order:
1 2 3 4 | Đánh răng Ăn sáng Đi học |
- Asynchronous (Asynchronous) : ie you have 3 jobs “Go to the market”, “Boil eggs”, “Sweep the house”. When you are done with “Shopping”, you should start “Cook”, but you find that “Cooking” takes too long to wait to save time then go “Scan house “always helps to avoid getting cheeks, So you put the boiled water for it, then you go to do the job “Sweeping the house”, not waiting for the boiled eggs to sweep the house, after sweeping the house, the eggs are also boiled and the result is always a delicious egg. and clean house.=> So in Javascript, asynchronous occurs when performing time-consuming tasks such as: request API to wait for API to return data (takes 2 minutes), or when using function setTimeout, Ajax, …. tasks This is like the job “Boil eggs” myself in the example above.
1 2 3 4 5 6 7 | console.log("Đi chợ"); function cookingEgg() { alert('Luộc trứng'); } setTimeout(cookingEgg, 1000); console.log("Quét nhà"); |
The result is as follows:
1 2 3 4 | Đi chợ Quét nhà Luộc trứng |
In the process you work with JavaScript, the synchronous (Synchronous) and asynchronous (Asynchronous) will certainly happen. Reading now, you will wonder “if in JavaScript there is such an asynchronous, then when you need data from the API to return to get that data to process the next thing?”. In the case below, how to solve it?
1 2 3 4 5 6 | // ví dụ lệnh bạn gọi api load list data user var dataList = axios.post('/api/ApiListUser/getList') // sau đó bạn xem dataList console.log('result:', dataList) |
Guess what the result is? Now waiting for the response when the API request goes to the database to get the data the user returns for me takes a long time, and the asynchronous JavaScript occurs, it will not wait for the returned data but it jumps into the console statement. and …. of course it doesn’t understand what dataList is to log out
=> This is when 3 guys (most common) handling the asynchronous order to put the correct order according to their wishes without jumping around like the example above in JavaScript came into being:
- Callback.
- Promise.
- Async / await.
Everything has a solution, right?
2. How does JavaScript execute?
JavaScript is a single thread language – ie at the moment only processing one thing. If so, when there is a task that takes 30 minutes, 1 hour, or even more than 1 hour because then you have to wait for this task to finish, then the browser will be frozen and blocked. So why can asynchronous JavaScript occur? So how does JavaScript work? I also find out!
JavaScript introduced it as a single-threaded language, which means it only has one Call Stack and only one thing at a time.
Call Stack : is a data structure stack (stack) used to store information about the operation of the computer program during execution, if the tasks take a lot of time (call api, ajax, setTimeout, callback , …) then these commands will be put into areas called WebAPIs.
WebAPIs : is the place that contains the tasks like: call api, ajax, setTimeout, callback, … I said above.
Callback Queue : The functions and tasks (all api, ajax, setTimeout, callback, …) will be put into the Callback Queue.
Event Loop : It is EL’s task to wait for the Call Stack to be empty and then check the Callback Queue to see if there is anything, if so, pick the first one and put it on the Call Stack to run.
3. Asynchronous handling in JavaScript using Callback, Promise and Async / Await
The purpose of the asynchronous handling I stated in the article above, if you forget you can read it again.
Callback
A callback is a function whose argument is function – a function that will be executed after another function has finished. Example using callback.
1 2 3 4 5 6 7 8 9 10 11 12 | function doHomework(subject, callback) { setTimeout( function(){ console.log(`Bắt đầu làm bài tập ${subject}.`); callback(); }, 5000); } function alertFinished(){ console.log('Làm bài tập xong!'); } doHomework('Toán', alertFinished); |
The results are returned according to what you want:
1 2 3 | // Bắt đầu làm bài tập Toán // Làm bài tập xong! |
At this point, a problem occurs that there will be a function nested function (callback too much nested) as shown below:
1 2 3 4 5 6 7 8 9 10 | api.getUser('api/listUser', function(err, user) { if (err) throw err api.getPostsOfUser(user, function(err, posts) { if (err) throw err api.getCommentsOfPosts(posts, function(err, comments) { // vân vân và mây mây... }) }) }) |
=> This case is called Callback hell and to solve this problem Promise was born.
Promise
Promises are a mechanism in JavaScript that helps you perform asynchronous tasks without falling into callback hell or pyramid of doom. The Promise takes two parameters
- Resolve: the function that will be called if the asynchronous code in the promise runs successfully.
- reject: will be called if the asynchronous code in a promise fails.
To create a promise object, you use the Promise class available in the browser as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | api.getUser = function(username) { // Hàm api.getUser() trả về một promise object return new Promise((resolve, reject) => { // Gửi AJAX request http.get(`/users/${username}`, (err, result) => { // Nếu có lỗi bên trong callback, chúng ta gọi đến hàm `reject()` if (err) return reject(err) // Ngược lại, dùng `resolve()` để trả dữ liệu về cho `.then()` resolve(result) }) }) } |
So api.getUser () will return a promise object. We can access the results returned by the .then () method .Promise also provides two methods: – .then (): to handle after the Promise has been successfully executed (when the resolve is called). . – .catch (): used to handle after Promise has any errors (when reject is called).
1 2 3 4 5 6 7 8 9 10 11 | promise() .then(() => { return 'foo' }) .then(result1 => { console.log(result1) // 'foo' return anotherPromise() }) .then(result2 => console.log(result2)) // `result2` sẽ là kết quả của anotherPromise() .catch(err => {}) |
A common mistake we make when we first get acquainted with Promise is creating “pyramid” promises like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | api .getUser('pikalong') .then(user => { api .getPostsOfUser(user) .then(posts => { api .getCommentsOfPosts(posts) .then(comments => { console.log(comments) }) .catch(err => console.log(err)) }) .catch(err => console.log(err)) }) .catch(err => console.log(err)) |
This is because we forgot about the chaining nature of promises, which allows the resolve function to return a synchronous value or another promise. So the workaround is:
1 2 3 4 5 6 7 8 9 | api .getUser('pikalong') // Trả về một promise .then(user => api.getPostsOfUser(user)) .then(posts => api.getCommentsOfPosts(posts)) .catch(err => { throw err }) |
In addition to that, the most popular and widely used method in asynchronous handling is Async / Await.
Async / Await
A sync / await is a mechanism that helps you to perform asynchronous operations more sequentially. Async / await still uses the Promise below, but your code will be clearer and easier to follow. To use this, you must declare the function with the async keyword. Then inside the function you can use await.
1 2 3 4 5 6 7 8 9 10 11 12 | async function() { try { const user = await api.getUser('pikalong') const posts = await api.getPostsOfUser(user) const comments = await api.getCommentsOfPosts(posts) console.log(comments) } catch (err) { console.log(err) } } |
Note that the output of the async function is always a Promise.
1 2 3 4 5 6 7 | async function hello() { return 1 } console.log(hello() instanceof Promise) // true hello().then(console.log) // 1 |
In essence, using async / await is to run Promise implicitly. Although async / await is more concise, easy to understand, there are cases where Promise should be better than async / await. The example is as follows:
1 2 3 4 5 6 7 | async function getABC () { let A = await getValueA ( ); // getValueA takes 2 seconds to fisnish let B = await getValueB ( ); // getValueB takes 4 seconds to fisnish let C = await getValueC ( ); // getValueC takes 3 seconds to fisnish return A * B * C; } |
At this point it is recommended to use Promise because the functions (getValueA, getValueB, ..) do not depend on each other, but attaching await takes time. => Using Promise.all The use of Promise.all () will ensure we have all the results of the functions before we execute the code afterward (they all run in parallel without waiting in sequence) Rewrite as Following use Promise.all ():
1 2 3 4 5 6 | async function getABC () { // Promise.all ( ) allows to sned all request at the same time. let results = await Promise.all ( [ getValueA, getValueB, getValueC ]); return results.reduce(( total, value ) => total * value); } |
Conclude
Hope that my article helps you understand some more about JavaScript. If my article has mistakes, comment below so I can correct my mistakes. Thank you. See you in the next posts!