Đơn luồng và đa luồng trong JavaScript là gì?

Đó là một buổi tối thứ bảy và đang trải qua một khóa học Udemy về Angular (một kỹ năng mới đang cố gắng đạt được). Trong một vài video, tôi nhận ra rằng kỹ năng Bản đánh máy của mình rất tệ và chuyển sang tài liệu của nó. Chà, trong một số chủ đề, tôi đã nghi ngờ về sự hiểu biết về Javascript của mình và tôi bắt đầu khám phá một số điều cơ bản. Và kết quả là blog này

Mặc dù ai cũng biết rằng “Javascript là ngôn ngữ đơn luồng”, vẫn luôn có một số nghi ngờ về điều này. Nếu Javascript là một luồng, thì nó hỗ trợ các cuộc gọi không đồng bộ như thế nào? . js, dựa trên thời gian chạy javascript, không bị chặn? . Và tôi quyết định ghi lại dòng suy nghĩ của mình ở đây để kết nối các điểm khác nhau liên quan đến việc hiểu các nguyên tắc cơ bản của Javascript

Câu hỏi và trả lời Javascript của tôi

Q. Đơn luồng nghĩa là gì?

A. Rằng sẽ chỉ có một luồng (quy trình) có sẵn để các hướng dẫn được thực thi

Q. Được rồi, Javascript có đơn luồng không?

A. Có, "thời gian chạy" Javascript là một luồng. Nó thực thi chương trình javascript. Nó duy trì một ngăn xếp duy nhất trong đó các lệnh được đẩy để kiểm soát thứ tự thực hiện và bật lên để được thực thi. Và một không gian heap nơi lưu trữ các tham chiếu đối tượng và thu gom rác

Hãy xem chương trình đơn giản này và xem nó được thực thi như thế nào

Khi tập lệnh (callstack. js) được thực thi, bộ thực thi javascript sẽ tạo bối cảnh thực thi chung, đẩy nó vào ngăn xếp (Hình 1, trạng thái 1) và quét xuống dưới. Tiếp theo, biến khởi tạo (a=10), sẽ được đẩy vào ngăn xếp. Xa hơn nữa là lệnh gọi hàm main(). Không giống như khởi tạo biến cho các lời gọi hàm, bộ thực thi tạo ngữ cảnh thực thi hàm mới và đẩy lên trên cùng của ngăn xếp lời gọi (Hình 1, trạng thái 2)

hình 1. Quản lý ngăn xếp thực thi Javascript

Cho đến khi điều khiển đến câu lệnh cuối cùng của hàm main() hoặc câu lệnh return, nó sẽ tiếp tục đẩy tất cả các câu lệnh vào ngăn xếp. Trong trường hợp của chúng tôi, bảng điều khiển. log() là câu lệnh cuối cùng và duy nhất của hàm main(), được bật lên và được thực thi (Hình 1 trạng thái 3). Khi tất cả các câu lệnh của hàm được thực thi, bộ thực thi sẽ bật ngữ cảnh thực thi hàm (Hình 1 trạng thái 3)

Ghi chú. Biến 'a' trong bảng điều khiển. câu lệnh log sẽ được tìm kiếm trong ngữ cảnh thực thi chức năng. Nếu nó không có sẵn, sau đó được tìm kiếm trong bối cảnh thực thi toàn cầu

Bộ thực thi sẽ đợi để xử lý bất kỳ câu lệnh nào khác, cho đến khi quá trình thực thi hàm main() kết thúc. Sau đó, nó đẩy dòng-6(callstack. js) vào ngăn xếp (Hình 1 trạng thái 4). Và điều tương tự sẽ được bật ra và thực thi (Hình 1 trạng thái 5). Cuối cùng, khi tất cả các câu lệnh của tập lệnh được thực thi, bối cảnh thực thi toàn cầu sẽ được bật ra, để lại ngăn xếp miễn phí cho các lần thực thi khác

Xin lưu ý. Ví dụ này quá đơn giản đối với bối cảnh này nhưng được chọn một cách có chủ ý để không đi chệch khỏi cuộc thảo luận cốt lõi. Có sự công bằng hơn cho chủ đề này trong hai con đường mòn này [con đường 1] [con đường 2], vui lòng đi đường vòng để xem giải thích chi tiết và quay lại

Q. Ok, có vẻ như nó được giải thích. Javascript có phải là ngôn ngữ được giải thích hoặc biên dịch không?

A. Vâng, nó phụ thuộc vào thời gian chạy. Javascript, theo thiết kế, là một ngôn ngữ lập trình được giải thích. Nó không cần bất kỳ trình biên dịch trung gian nào để chuyển đổi thành mã máy có thể đọc được như Java. Mặc dù điều đó đúng, nhưng các trình duyệt hiện đại đã triển khai thời gian chạy với rất nhiều tiện ích bổ sung cải thiện hiệu suất. Một trong những bổ sung chính là trình biên dịch JIT (Just In Time) sẽ chuyển đổi mã javascript thành ngôn ngữ máy trung gian trước khi trình duyệt diễn giải nó. Một số ví dụ thời gian chạy javascript phổ biến tuân theo các tiêu chuẩn này là V8 — Google chrome

Q. Ok, quay lại câu hỏi ban đầu. Chà, nếu Javascript là một luồng, làm thế nào để hàm setTimeout không bị chặn và việc thực thi của nó bị hoãn lại và điều gì sẽ chặn/đóng băng trình duyệt hoặc ngăn xếp?

A. Trước tiên, hãy bắt đầu với việc chặn bằng một mẫu mã nhanh

Output : 
Hit zero at : 5
return

Trong hàm longRunning() ở trên, vòng lặp while chặn ngăn xếp cuộc gọi cho đến khi đáp ứng giới hạn cứu trợ (điều kiện kết thúc). Độ dài của thời gian chặn có thể thay đổi từ vài giây đến vài phút, tùy thuộc vào lựa chọn hạt giống và cứu trợ. Đây là những hậu quả điển hình của việc không xử lý đúng cách các quy trình chạy dài trong Javascript

Hãy thực hiện một số thay đổi bằng cách giới thiệu setTimeout() tại đây

Output: 
return
Hit zero at : 5

Lưu ý nhật ký “return” xuất hiện trước kết quả. Đầu ra chứng minh điểm rõ ràng trong câu hỏi, rằng việc thực thi setTimeout bị hoãn lại và không chặn việc thực thi ngăn xếp javascript. Lý do có một câu trả lời ngắn và dài hơn. Câu trả lời ngắn gọn là, setTimeout không phải là một tính năng javascript, nó được cung cấp bởi trình duyệt. Trình duyệt kiểm soát trình kích hoạt và thực thi phương thức setTimeout không đồng bộ

Q. Và câu trả lời dài là?

A. Câu trả lời dài cần giới thiệu về một vài tính năng khác của trình duyệt bổ sung cho khả năng của mã Javascript

Họ đang,

  • API web
  • Vòng lặp sự kiện

[Thực ra, setTimeout là một phương thức của đối tượng cửa sổ. Đối tượng cửa sổ đại diện cho một cửa sổ/tab của trình duyệt. ]

API Web là một bộ API cung cấp một số khả năng nổi tiếng như AJAX và một số khả năng đặc biệt đối với mã Javascript như bộ đệm, xử lý tệp âm thanh, định vị địa lý, thông báo, v.v. Và, đây là danh sách đầy đủ các API do Chrome cung cấp

Vòng lặp sự kiện đóng một vai trò quan trọng trong việc thực thi các API và phương thức web, của đối tượng cửa sổ một cách không đồng bộ. Vẫn còn một số ẩn số sẽ được giới thiệu để hiểu cách thức hoạt động của vòng lặp sự kiện. Họ đang,

  • Bảng sự kiện - duy trì trình kích hoạt của các cuộc gọi không đồng bộ so với tham chiếu cho các phương thức gọi lại
  • Hàng đợi sự kiện — là trình giữ chỗ để tạm thời giữ các tham chiếu của phương thức gọi lại trước khi nó có thể được đẩy vào ngăn xếp thời gian chạy javascript

Bây giờ hãy xem cách cả ba hoạt động cùng nhau. Thời điểm khi mã Javascript gọi một phương thức không đồng bộ (setTimeout trong trường hợp của chúng tôi), cuộc gọi sẽ bị hoãn lại từ ngăn xếp thời gian chạy javascript và được thêm vào Bảng sự kiện do trình duyệt duy trì. Bảng sự kiện theo dõi các chức năng này với tham chiếu đến điểm kích hoạt của nó (trong trường hợp của chúng tôi là bộ đếm thời gian — Hình 2. giai đoạn 1)

Ngay khi trình kích hoạt tắt, nó sẽ di chuyển cuộc gọi lại được đính kèm với phương thức không đồng bộ (hàm thực hiện vòng lặp while trong trường hợp của chúng tôi) sang “Hàng đợi sự kiện” (Hình 2. bang2). Hàng đợi sự kiện quản lý cấu trúc dữ liệu hàng đợi và gửi các thông báo được thêm vào cấu trúc đó theo kiểu FIFO (vào trước ra trước)

Cuối cùng, đây là vòng lặp Sự kiện của chúng tôi, đây là một quy trình chạy liên tục để theo dõi xem ngăn xếp cuộc gọi có trống không. Khi nó thấy ngăn xếp cuộc gọi trống, nó sẽ lấy tin nhắn đầu tiên từ hàng đợi và đặt nó vào ngăn xếp (Hình 2 trạng thái 3). Đây là một bài viết xuất sắc về vòng lặp Sự kiện, nếu bạn muốn

Fig2 các trạng thái khác nhau gọi ngăn xếp/bảng sự kiện/hàng đợi sự kiện trong khi thực hiện chức năng không đồng bộ

Q. Hmmm Ok, vậy làm thế nào để tất cả gắn kết với nhau?

A. Ok, hãy cố gắng trả lời câu hỏi chính của chúng tôi. Vì vậy, rõ ràng là, mặc dù bản thân thời gian chạy Javascript không phải là không đồng bộ, nhưng nó đang chặn và không đồng thời. Trình duyệt quản lý thời gian chạy Javascript cung cấp tất cả các khả năng bổ sung cho mã Javascript (không đồng bộ, không chặn và đồng thời) thông qua API web. Nơi vòng lặp Sự kiện, bảng Sự kiện và Hàng đợi đặc biệt của chúng tôi quản lý trạng thái của các API web và đẩy các lệnh gọi lại vào ngăn xếp vào đúng thời điểm như đã giải thích ở trên

Phần kết luận

Như đã đề cập trong lời nói đầu, blog này là một phần trong nhiệm vụ của tôi để hiểu các nguyên tắc cơ bản của Javascript. Và tôi quyết định ghi lại dòng suy nghĩ theo thứ tự nó diễn ra và tập hợp các câu trả lời khi tôi xem qua các bài báo và blog. Tôi không chắc đó có phải là một cách hay để giải thích mọi thứ hay không nhưng tôi được truyền cảm hứng bởi niềm vui khi giải thích những điều tầm thường và không tầm thường cho trẻ em cũng như cách chúng xử lý ý tưởng bằng cách đặt câu hỏi. Nếu bạn muốn biết thêm, dưới đây là một kinh nghiệm như vậy của tôi

Tôi đã làm thế nào để khiến đứa con gái 7 tuổi của mình cảm thấy Zero?

Luôn luôn là một việc tuyệt vời để giải thích cho ai đó về điều gì đó mà mắt người không nhìn thấy/rõ ràng, bắt đầu từ…

Trung bình. com

Xin thứ lỗi cho tôi ngắn gọn về một số chủ đề. Tôi đã làm điều đó một cách thận trọng để duy trì tính liên tục của blog này nhưng tôi đảm bảo đề cập đến các tài liệu tham khảo để giải thích chi tiết, theo cách cũng để ghi công cho những tác giả đó

Chuỗi đơn và đa luồng trong JavaScript là gì?

js chạy mã JavaScript trong một luồng đơn lẻ, nghĩa là mã của bạn chỉ có thể thực hiện một tác vụ tại một thời điểm . Tuy nhiên, nút. bản thân js là đa luồng và cung cấp các luồng ẩn thông qua thư viện libuv, xử lý các hoạt động I/O như đọc tệp từ đĩa hoặc yêu cầu mạng.

Sự khác biệt giữa đa luồng và đơn luồng là gì?

"Đơn luồng" có nghĩa là chúng tôi mở một kết nối duy nhất và đo tốc độ từ đó. "Đa luồng" có nghĩa là chúng tôi đang sử dụng nhiều kết nối - thường là từ 3 đến 8 - cùng một lúc và đo tổng tốc độ trên tất cả các kết nối đó

Đơn luồng có nghĩa là gì trong JS?

JavaScript được biết đến là đơn luồng do đặc tính của nó là chỉ có một ngăn xếp lệnh gọi , điều mà một số ngôn ngữ lập trình khác có nhiều. Các chức năng JavaScript được thực thi trên ngăn xếp cuộc gọi, theo LIFO (Last In First Out). Ví dụ, chúng ta có một đoạn mã như thế này. const foo = () => {

Đa luồng trong JavaScript là gì?

Dữ liệu được gửi giữa luồng chính và công nhân thông qua tin nhắn . Vì các worker này chạy trên một luồng riêng biệt với luồng thực thi chính, nên bạn có thể sử dụng web worker để chạy các tác vụ xử lý chuyên sâu từ trình duyệt mà không tạo các phiên bản chặn.