Javascript: Event Loop và Call Stack là gì?

Hôm nay, chúng ta tìm hiểu sâu hơn một chút về Javascript, những nhân vật hậu trường làm nên sức mạnh của ngôn ngữ này. Hiểu được Event Loop Call Stack giúp chúng ta có cái nhìn kỹ hơn về hiệu năng của Javascript, cũng như cách thức một ngôn ngữ đơn luồng(single-threaded) và đồng bộ(syncronous) hoạt động.

Sau đây là một số thành phần chính của một browser:

  • Heap: Các state trong Javascript sẽ được lưu ở đây, mỗi đối tượng sẽ được cấp bộ nhớ để lưu trữ khi chúng được khai báo.
  • Event Loop: là một Queue, tất cả cá event được push vào Queue này, mỗi khi một sự kiện được phát ra nó sẽ được push vào Queue. Trong Queue này, thứ tự thực hiện là vào trước thì sẽ được xử lí trước, vào sau thì được xử lí sau.
  • Stack: đây là phần single threaded của Javascript, nó sẽ sắp xếp các hàm và thực thi chúng theo nguyên lý của stack là vào trước thực thi sau, vào sau thì thực thi trước.
  • Browser hay Web APIs: được build trong browser của bạn, đó là những APIs của trình duyệt, chứ không phải của Javascript như Mouse Event, XMLHttpRequest, Geolocation,…

Chúng ta cùng xem một ví dụ nhé:

function main(){
  console.log('A');
  setTimeout(
    function display(){ console.log('B'); }
  ,2000);
  console.log('C');
}
main();
//	Output
//	A
//	C
//      B

Ta có một hàm main với hai console.log sẽ log ra màn hình là A và C và ở giữa là một hàm setTimeout với 2000ms là console.log(‘B’).

  1. Đầu tiên hàm main được push vào trong Call Stack. Sau đó dòng lệnh console.log(‘A’) cũng được thêm vào Stack và được thực thi in ra A. Sau đó, console.log(‘A’) được xóa khỏi Stack.
  2. Sau đó, hàm setTimeout được push vào Stack với một callback và timer là 2000ms. setTimeout là một Browser APIs, nên được giao lại cho Browser xử lí timer này. Callback của setTimeout được Web APIs giữ cho tới khi đúng với số thời gian timeout, ở đây là 2000ms. Callback này sẽ tự động được push vào Event Queue sau 2000ms nữa. setTimeout được xóa khỏi Stack.
  3. Kế đến, console.log(‘C’) được push vào Stack và được thực thi(invoke), in ra C. Sau đó, console.log(‘C’) được xóa khỏi Stack.
  4. Tiếp theo, hàm main đã thực thi xong và cũng được xóa khỏi Stack. Lúc này, Event Loop đã nhận callback exec() của setTimeout được chờ xử lý từ bước 2.
  5. Bạn còn nhớ ở bước 2 không? Chúng ta đã giao lại setTimeout cho Browser APIs xử lí, đến lúc này Event Loop có một callback exec(), nó sẽ được push vào Stack và in ra B. Sau đó, exec() của setTimeout cũng được xóa khỏi Stack.

Trên đây là một ví dụ đơn giản về cách thức hoạt động bên trong của Javascript. Bạn sẽ hiểu được tại sao Javascipt chỉ là đơn luồng và đồng bộ. Nó chỉ có một Call Stack nên được gọi là đơn luồng và các câu lệnh sẽ được thực thi tuần tự trong Stack nên được gọi là đồng bộ.

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *