-->
ads here

Event loop in javascript

advertise here
Như ta đã biết JavaScript là một ngôn ngữ single-thread nhưng có khả năng hỗ trợ concurrency thông qua các khái niệm event và callback. Những API của JavaScript là bất đồng bộ và single-threaded, và nó sử dụng những lời gọi hàm bất đồng bộ để duy trì concurrency. JavaScript sử dụng Observer pattern, nó sẽ luôn quan sát 1 vòng lặp sự kiện - Event loop và khi bất cứ task nào được thực hiện xong, nó sẽ kích hoạt 1 event tương ứng báo hiệu cho các hàm lăng nghe sự kiện  - event listener thực thi. Và hôm nay chúng ta sẽ tìm hiểu xem Event loop là gì thông qua bài viết này.
Bài viết gồm 3 mục chính:

  1. Event loop là gì?
  2. Các khái niệm xung quanh event loop
  3. How event loop work?

1. Event loop là gì?

Như ta đã biết, JavaScript là single-threaded, tuy nhiên nó vẫn có khả năng xử lý các tác vụ IO non-blocking là nhờ có vòng lặp sự kiên - Event loop. Để dễ hiểu hơn ta sẽ lấy một ví dụ về gọi AJAX như sau: 
Giả sử A là một chương trình JS, gọi 1 AJAX request đến server là đợi kết quả về. Kết quả sẽ đc một hàm callback xử lý gọi là CB. Và môi trường chứa trương chính JS đang chạy là H (Host)
Khi tạo 1 request AJAX, A sẽ nói với H rằng: "Ê, giờ tao tạm dừng thực hiện để lấy dữ liệu từ server về. Khi nào dữ liệu về tới mày kêu thằng CB xử lý zùm tao nha!". Thằng H sẽ sau đó sẽ chờ response chứa dữ liệu về, sau đó khi dữ liệu tới nơi, nó sẽ lên schedule cho CB được thực hiện bằng cách thêm CB vào event loop.
Chúng ta sẽ mô tả kĩ hơn event loop thông qua đoạn mã giả sau:

1:  // `eventLoop` is an array that acts as a queue (first-in, first-out)  
2:  var eventLoop = [ ];  
3:  var event;  
4:  // keep going "forever"  
5:  while (true) {  
6:      // perform a "tick"  
7:      if (eventLoop.length > 0) {  
8:          // get the next event in the queue  
9:          event = eventLoop.shift();  
10:          // now, execute the next event  
11:          try {  
12:              event();  
13:          }  
14:          catch (err) {  
15:              reportError(err);  
16:          }  
17:      }  
18:  }

Event loop hoạt động như một hàng đợi queue bên trong một vòng lặp liên tục while-true, mỗi khi hàng đợi có ít nhất 1 event (eventLoop.length > 0) thì event đó sẽ được lấy ra khỏi hàng đợi và được thực hiện. Event này chính là hàm callback hay chính là thằng CB ở ví dụ trên.

2. Các khái niệm xung quanh Event loop

Vùng nhớ Heap: Là vùng nhớ không có cấu trúc, nơi các object JS được cấp phát
Vùng nhớ Stack: Là vùng nhớ làm nên tính single-threaded của JS, đây chính là nơi các function đc thực thi
Browser và WebAPI: được tích hợp sẵn có trong trình duyệt, có khả năng lấy dữ liệu từ trình duyệt và môi trường xung quanh để sử dụng
Callback queue: Hàng đợi chứa các callback (cách mà event loop hoạt động)

Sau khi đã nắm được các khái niệm, chúng ta sẽ đi tìm hiểu xem event loop vận hành thực tế với các câu lệnh như thế nào?

3. How Event loop work?

Để hiểu rõ hơn các hoạt động của event loop thế nào ta sẽ đi qua 2 ví dụ sau:

Ví dụ 1: Ta có đoạn code sau:


1:  function main(){  
2:   console.log(1);  
3:   setTimeout(  
4:    function display(){ console.log(2); }  
5:   ,0);  
6:      console.log(3);  
7:  }  
8:  main(); 


Bước 1: Push main() vào trong Stack, bắt đầu thực hiện bên trong hàm main().
    • Stack: main()
    • Queue: null
    • Output: <empty>
Bước 2: Push console.log(1) vào Stack, sau đó thực hiện in ra màn hình.
    • Stack: main(), console.log(1)
    • Queue: null,
    • Output: 1
Bước 3: Sau khi thực hiện xong, Pop console.log(1) ra khỏi Stack
    • Stack: main()
    • Queue: null,
    • Output: 1
Bước 4: Push setTimeout( function(display () {console.log(2);}, 0), vào stack, sau đó thực hiện setTimeout. setTimeout là WebAPI nên khi đó nó sẽ đăng kí 1 event là timeout 0 ms và callback là console.log(2).
    • Stack: main(), setTimeout()
    • Queue: null,
    • Output: 1
Bước 5: Sau khi đăng kí event và callback xong, setTimeout sẽ được Pop ra khỏi Stack, đồng thời đẩy callback console.log(2) vào Queue:
    • Stack: main()
    • Queue: console.log(2),
    • Output: 1
Bước 6: Push console.log(3) vào Stack, sau đó thực hiện in ra màn hình.
    • Stack: main(), console.log(3)
    • Queue: console.log(2),
    • Output: 1<\n>3
Bước 7: Sau khi thực hiện xong, Pop console.log(3) khỏi Stack;
    • Stack: main()
    • Queue: console.log(2),
    • Output: 1<\n>3
Bước 8: Bên trong hàm main() đã thực hiện xong, Pop hàm main() ra khỏi Stack
    • Stack: null
    • Queue: console.log(2),
    • Output: 1<\n>3
Bước 9: Đây là show time của event loop. Event loop thấy Stack đã trống đồng thời có hàm đang nằm đợi trong Queue. Khi đó Push console.log(2) vào Stack. sau đó thực hiện in ra màn hình.
    • Stack: console.log(2)
    • Queue: null
    • Output: 1<\n>3<\n>2
Bước 10: Sau khi thực hiện xong, Pop console.log(2) ra khỏi Stack, đoạn code hoàn thành.
    • Stack: console.log(2)
    • Queue: null
    • Output: 1<\n>3<\n>2
Kết quả của đoạn code trên là in ra màn hình
1
3
2

Kết

Event loop là cơ chế giúp JS hiện thực concurency mặc dù bản thân JS là single threaded. Nhờ có event loop thì chúng ta có thể thực hiện được các lời gọi hàm bất đồng bộ trên JS như fetch dữ liệu từ server hay đọc data từ ổ cứng...

Cảm ơn mọi người đã dành thời gian đọc bài viết của mình. Nếu có ý kiến đóng góp thì đừng ngại comment phía dưới. Nếu thấy hay có thể chia sẻ cho mọi người cùng biết nhé.
PS: Các bạn có thể tìm hiểu thêm về callback trong NodeJS qua bài 1 bài viết của mình tại đây. ^^

Reference:

Advertisement
COMMENTS ()