- vừa được xem lúc

Javascript: Event Loop và Call Stack

0 0 77

Người đăng: Đăng Sang Nguyễn

Theo Viblo Asia

Giới thiệu

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 và 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.
Dưới đây phần tóm tắt về cách JavaScript tương tác với trình duyệt:
image.png
Lưu ý rằng hầu hết những thứ trong hình ảnh không phải là một phần của chính ngôn ngữ JavaScript. Web APIs, Call Stack và Event Loop là tất cả các tính năng mà trình duyệt cung cấp. Chúng ta cùng tìm hiểu thôi.

Call stack

Bạn có thể đã nghe nói rằng JavaScript là một luồng. Nhưng nó có nghĩa gì?
JavaScript có thể làm một việc duy nhất tại một thời điểm vì nó chỉ có một ngăn xếp để gọi lệnh.
Call statck là một cơ chế giúp trình thông dịch JavaScript theo dõi các chức năng mà một tập lệnh gọi .
Mỗi khi tập lệnh hoặc hàm gọi một hàm, nó sẽ được thêm vào đầu ngăn xếp. Mỗi khi hàm thoát , trình thông dịch sẽ xóa nó khỏi ngăn xếp hàm gọi đó .
Một hàm thoát ra thông qua câu lệnh trả về hoặc bằng cách đến cuối phạm vi.
Ví dụ:

function task(message) { // emulate time consuming task let n = 10000000000; while (n > 0){ n--; } console.log(message);
} console.log('Start script...');
task('Download a file.');
console.log('Done!');
//kết quả sẽ là:
//Start script...
//Download a file.
//Done!

Hình dưới mô tả quá trình thực thi:
image.png Khi bạn cố ý thực hiện đoạn code dưới đây:

function b() { a();
}
function a() { b();
}
b();

thì sẽ xuất hiện lỗi Uncaught RangeError: Maximum call stack size exceeded tức là một hàm đã được gọi quá nhiều lần dẫn đến tràn ngăn xếp. Kích thước ngăn xếp cuộc gọi tối đa nằm trong khoảng từ 10 đến 50 nghìn cuộc gọi , vì vậy nếu bạn vượt quá kích thước đó, rất có thể bạn có một vòng lặp vô hạn trong mã của mình.

Bộ nhớ Heap

Hiểu đơn giản JavaScript heap là nơi các đối tượng được lưu trữ khi chúng ta xác định các hàm hoặc biến.

Web APIs

Như phần giới thiệu, JS là một ngôn ngữ đồng bộ và chạy đơn luồng nhưng ta vẫn có thể thực hiện mọi việc đồng thời trong trình duyệt . Như tiêu đề đã gợi ý, điều này có thể thực hiện được thông qua các API mà trình duyệt cung cấp.
Một ưu điểm khác của các API web là chúng được viết bằng mã cấp thấp hơn (như C), cho phép chúng thực hiện những điều đơn giản là không thể thực hiện được trong JavaScript đơn thuần.
Chúng cho phép bạn thực hiện các yêu cầu AJAX hoặc thao tác với DOM, ngoài ra còn có nhiều thứ khác, như theo dõi địa lý, truy cập bộ nhớ cục bộ, service workers, v.v.
Bạn xem hình dưới để thấy rõ vai trò của Web APIs nhé: image.png

Callback queue

Ta có ví dụ sau:

const a = () => console.log('a');
const b = () => setTimeout(() => console.log('b'), 100);
const c = () => console.log('c'); a();
b();
c();

setTimeout đang được thực thi đồng thời trong khi trình thông dịch JS tiếp tục thực thi các câu lệnh tiếp theo.
Khi hết thời gian chờ và call stack trống, console.log('b') được truyền đến callback quere để được thực thi lại.
Và ta có kết quả như sau:

//a
//c
//b

Event loop

Event loop JavaScript nhận cuộc gọi đầu tiên trong callback quere và thêm nó vào call stack ngay khi nó trống.
Mã JavaScript đang được chạy theo cách chạy đến hoàn thành, có nghĩa là nếucall stack hiện đang thực thi một số mã, Event loop sẽ bị chặn và sẽ không thêm bất kỳ lệnh gọi nào từ hàng đợi cho đến khi ngăn xếp trống trở lại .
Đó là lý do tại sao điều quan trọng là không chặn ngăn xếp cuộc gọi bằng cách chạy các tác vụ tính toán nhiều.
Nếu bạn thực thi quá nhiều mã hoặc làm tắc nghẽn hàng đợi gọi lại, trang web của bạn sẽ không phản hồi, vì nó không thể thực thi bất kỳ mã JavaScript mới nào.
Các trình xử lý sự kiện, chẳng hạn như onscroll, thêm nhiều tác vụ hơn vào callback quere khi được kích hoạt. Đó là lý do tại sao bạn nên gỡ bỏ các lệnh gọi lại này, nghĩa là chúng sẽ chỉ được thực thi sau mỗi x ms.

window.onscroll = () => console.log('scroll');

Khi cuộn, bạn có thể quan sát tần suất bản in gọi lại scroll.

setTimeout (fn, 0)

Chúng ta có thể tận dụng hành vi được mô tả ở trên nếu chúng ta muốn thực thi một số tác vụ mà không chặn luồng chính quá lâu.
Đặt mã không đồng bộ của bạn trong một cuộc gọi lại và đặt setTimeoutthành 0ms sẽ cho phép trình duyệt thực hiện những việc như cập nhật DOM trước khi tiếp tục thực hiện lệnh gọi lại.

Kết luận

Trên đây là một kiến thức đơ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ộ. Cảm ơn các bạn đã xem.

Tài liệu tham khảo

Link 1: http://thaunguyen.com/blog/javascript/javascript-event-loop-va-call-stack-la-gi
Link 2: https://felixgerschau.com/javascript-event-loop-call-stack/

Bình luận

Bài viết tương tự

- vừa được xem lúc

2021, chúng ta cần tối ưu hóa việc tải hình ảnh trên web như nào?

Rất chào các bạn,. Như các bạn đã biết, trong kỉ nguyên công nghệ, song song với sự sinh ra dày đặc của các trang web mới cũng là sự biến mất của những trang web "lạc hậu" hay hoạt động kém hiệu quả.

0 0 43

- vừa được xem lúc

Cách mình "hack" được vào hẹ thống của SMAS để xem điểm.

Cách mà mình "hack" được vào hệ thống của SMAS. Thật ra dùng từ hack cũng không đúng lắm, chỉ là một vài trick để lừa hệ thống mà thôi.

0 0 124

- vừa được xem lúc

Giải thích một số JAVASCRIPT ARRAY METHOD với EMOJIS

Như chúng ta đã biết, Array trong JS có rất nhiều method tiện dụng có thể hỗ trợ chúng ta. Sau đây là một số method thông dụng được giải thích bằng các emoji. Thêm một hoặc nhiều phần tử vào sau mảng. livestock.

0 0 33

- vừa được xem lúc

Testing trong Javascript với Jest (Phần 1)

Hello 500 anh em, lại là mình đây. Chú bé coder yêu màu tím thích màu hồng và ghét sự giả dối đây .

0 0 249

- vừa được xem lúc

Áp dụng kiến trúc 3 Layer Architecture vào project NodeJS

The problem encountered. Các framework nodejs phổ biết như Express cho phép chúng ta dễ dàng tạo ra Resful API xử lí các request từ phía client một cách nhanh chóng và linh hoạt.

0 0 64

- vừa được xem lúc

Một số String methods cần biết trong javascript

String là một trong những phần quan trọng nhất trong javascript, ngoài những methods hay dùng như trim, concat, subString, toUpperCase, toLowerCase; Javascript còn cung cấp cho chúng ta rất nhiều methods hữu ích khác để thao tác và giải quyết các vấn đề dễ dàng hơn khi làm việc với String. Mặc dù nh

0 0 25