Mặc dù có thể cần một sự hiểu biết sâu sắc về các ngôn ngữ như C ++ và C để viết mã sản xuất quy mô đầy đủ, JavaScript thường có thể được viết chỉ với một sự hiểu biết cơ bản về những gì có thể được thực hiện với ngôn ngữ.

Các khái niệm, như chuyển các cuộc gọi lại cho các hàm hoặc viết mã không đồng bộ, thường không quá khó để thực hiện, điều này làm cho hầu hết các nhà phát triển JavaScript ít quan tâm đến những gì diễn ra dưới mui xe. Họ chỉ quan tâm đến việc hiểu về sự phức tạp đã bị trừu tượng hóa bởi chúng bởi ngôn ngữ.

Là một nhà phát triển JavaScript, việc hiểu những gì thực sự xảy ra dưới mui xe ngày càng trở nên quan trọng và làm thế nào hầu hết những sự phức tạp này được trừu tượng hóa từ chúng ta thực sự hoạt động. Nó giúp chúng tôi đưa ra quyết định sáng suốt hơn, từ đó có thể tăng hiệu suất mã của chúng tôi một cách mạnh mẽ.

Bài viết này tập trung vào một trong những khái niệm hoặc thuật ngữ rất quan trọng nhưng hiếm khi được hiểu trong JavaScript. Các SỰ KIỆN!. 

Viết mã không đồng bộ không thể tránh được trong JavaScript, nhưng tại sao mã chạy không đồng bộ thực sự có nghĩa? I E. Vòng lặp sự kiện

Trước khi chúng ta có thể hiểu cách vòng lặp sự kiện hoạt động, trước tiên chúng ta phải hiểu chính JavaScript là gì và cách thức hoạt động của nó!

JavaScript là gì?

Trước khi chúng tôi tiến hành, tôi đã muốn chúng tôi lùi một bước về những điều cơ bản. JavaScript thực sự là gì? Chúng ta có thể định nghĩa JavaScript là;

JavaScript là một ngôn ngữ đồng thời, không bị chặn, được giải thích, đơn luồng.

Đợi đã, cái gì thế này? Một định nghĩa bookish? ��

Hãy để phá vỡ nó!

Các từ khóa ở đây liên quan đến bài viết này là đơn luồng, không chặn, đồng thời,không đồng bộ.

Chủ đề đơn

Một chuỗi thực hiện là chuỗi lệnh nhỏ nhất được lập trình có thể được quản lý độc lập bởi bộ lập lịch. Một ngôn ngữ lập trình là một luồng đơn có nghĩa là nó chỉ có thể thực hiện một tác vụ hoặc hoạt động tại một thời điểm. Điều này có nghĩa là nó sẽ thực thi toàn bộ quá trình từ đầu đến cuối mà không bị gián đoạn hoặc dừng luồng.

Không giống như các ngôn ngữ đa luồng, trong đó nhiều tiến trình có thể được chạy trên nhiều luồng đồng thời mà không chặn lẫn nhau.

Làm thế nào JavaScript có thể là một luồng đơn và không chặn đồng thời?

Nhưng chặn có nghĩa là gì?

Không chặn

Không có một định nghĩa về chặn; nó chỉ đơn giản có nghĩa là những thứ đang chạy chậm trên chuỗi. Vì vậy, không chặn có nghĩa là những thứ phát sinh chậm trên luồng.

Nhưng chờ đã, tôi đã nói JavaScript chạy trên một luồng chưa? Và tôi cũng nói nó không chặn, có nghĩa là tác vụ chạy nhanh trên ngăn xếp cuộc gọi? Nhưng bằng cách nào??? Làm thế nào về khi chúng ta chạy bộ tính giờ? Vòng lặp?

Thư giãn! Chúng tôi tìm hiểu một chút.

Đồng thời

Đồng thời có nghĩa là mã đang được thực thi đồng thời bởi nhiều hơn một luồng.

Được rồi, mọi thứ đang thực sự kỳ dị bây giờ, làm thế nào JavaScript có thể là một luồng đơn và đồng thời cùng một lúc? tức là, thực thi mã của nó với nhiều hơn một luồng?

Không đồng bộ

Lập trình không đồng bộ có nghĩa là mã chạy trong một vòng lặp sự kiện. Khi có một hoạt động chặn, sự kiện được bắt đầu. Mã chặn tiếp tục chạy mà không chặn luồng thực thi chính. Khi mã chặn kết thúc chạy, nó xếp hàng LÊN kết quả của các hoạt động chặn và đẩy chúng trở lại ngăn xếp.

Nhưng JavaScript có một chủ đề duy nhất? Điều gì sau đó thực thi mã chặn này trong khi để các mã khác trong luồng được thực thi?

Trước khi chúng tôi tiến hành, hãy để có một bản tóm tắt về những điều trên.

  • JavaScript là một luồng đơn
  • JavaScript không chặn, tức là các quy trình chậm don don chặn thực thi của nó
  • JavaScript là đồng thời, tức là nó thực thi mã của nó trong nhiều hơn một luồng cùng một lúc
  • JavaScript không đồng bộ, tức là, nó chạy mã chặn ở một nơi khác.

Nhưng phần trên không chính xác cộng lại, làm thế nào một ngôn ngữ đơn luồng không bị chặn, đồng thời và không đồng bộ?

Hãy để sâu hơn một chút, hãy để sâu xuống các công cụ thời gian chạy JavaScript, V8, có lẽ nó có một số chủ đề ẩn mà chúng tôi không biết về.

Động cơ V8

Công cụ V8 là một công cụ thời gian chạy lắp ráp web nguồn mở, hiệu suất cao dành cho JavaScript được viết bằng C ++ bởi Google. Hầu hết các trình duyệt chạy JavaScript bằng công cụ V8 và ngay cả môi trường thời gian chạy js nút phổ biến cũng sử dụng nó.

Trong tiếng Anh đơn giản, V8 là một chương trình C ++, nhận mã JavaScript, biên dịch và thực thi nó.

V8 làm hai việc chính;

  • Phân bổ bộ nhớ heap
  • Bối cảnh thực hiện ngăn xếp cuộc gọi

Đáng buồn thay, sự nghi ngờ của chúng tôi đã sai. V8 chỉ có một ngăn xếp cuộc gọi, hãy nghĩ rằng ngăn xếp cuộc gọi là chuỗi.

Một luồng === một ngăn xếp cuộc gọi === một lần thực hiện tại một thời điểm.

Hình ảnh – Hacker Trưa

Vì V8 chỉ có một ngăn xếp cuộc gọi, nên JavaScript chạy đồng thời và không đồng bộ như thế nào mà không chặn luồng thực thi chính?

Hãy cùng cố gắng tìm hiểu bằng cách viết một mã không đồng bộ đơn giản nhưng phổ biến và phân tích nó cùng nhau.

JavaScript chạy từng dòng mã theo từng dòng, từng dòng một (luồng đơn). Như mong đợi, dòng đầu tiên được in trong bảng điều khiển ở đây, nhưng tại sao dòng cuối cùng được in trước mã hết thời gian? Tại sao không phải quá trình thực thi chờ mã thời gian chờ (chặn) trước khi tiếp tục chạy dòng cuối cùng?

Một số luồng khác dường như đã giúp chúng tôi thực hiện thời gian chờ đó vì chúng tôi khá chắc chắn rằng một luồng chỉ có thể thực hiện một nhiệm vụ duy nhất tại bất kỳ thời điểm nào.

Hãy để Lén lén nhìn vào Mã nguồn V8 trong một thời gian.

Chờ đợi gì ?? !!! Không có chức năng hẹn giờ trong V8, không có DOM? Không có sự kiện? Không có AJAX? LỚN. Yeeeeessss!!!

Sự kiện, DOM, bộ hẹn giờ, v.v … không phải là một phần của việc triển khai lõi JavaScript, JavaScript tuân thủ nghiêm ngặt các thông số kỹ thuật của Tập lệnh Ecma và các phiên bản khác nhau của nó thường được đề cập theo Thông số kỹ thuật tập lệnh Ecma (ES X).

Quy trình thực hiện

Các sự kiện, bộ hẹn giờ, yêu cầu Ajax đều được các trình duyệt cung cấp ở phía máy khách và thường được gọi là API Web. Chúng là những cái cho phép JavaScript đơn luồng không bị chặn, đồng thời và không đồng bộ! Nhưng bằng cách nào?

Có ba phần chính trong quy trình thực hiện của bất kỳ chương trình JavaScript nào, ngăn xếp cuộc gọi, API web và hàng đợi Nhiệm vụ.

Ngăn xếp cuộc gọi

Một ngăn xếp là một cấu trúc dữ liệu trong đó phần tử cuối cùng được thêm vào luôn là phần tử đầu tiên được loại bỏ khỏi ngăn xếp, bạn có thể nghĩ nó là một chồng của một tấm trong đó chỉ có tấm đầu tiên được thêm vào cuối cùng mới có thể được gỡ bỏ trước. Call Stack đơn giản là không có gì ngoài cấu trúc dữ liệu ngăn xếp trong đó các tác vụ hoặc mã đang được thực thi tương ứng.

Hãy xem xét ví dụ dưới đây;

Nguồn – https://youtu.be/8aGhZQkoFbQ

Khi bạn gọi hàm printSapes (), nó được đẩy lên ngăn xếp cuộc gọi, hàm printSapes () gọi hàm vuông (). Hàm vuông () được đẩy lên ngăn xếp và cũng gọi hàm bội (). Hàm nhân được đẩy lên ngăn xếp. Vì hàm bội trả về và là thứ cuối cùng được đẩy vào ngăn xếp, nên nó được giải quyết trước và được xóa khỏi ngăn xếp, tiếp theo là hàm vuông () và sau đó là hàm printSapes ().

API web

Đây là nơi mà mã được xử lý bởi động cơ V8 được thực thi để không chặn khối khối luồng xử lý chính. Khi Ngăn xếp cuộc gọi gặp chức năng API web, quy trình ngay lập tức được bàn giao cho API Web, nơi nó đang được thực thi và giải phóng Ngăn xếp cuộc gọi để thực hiện các hoạt động khác trong quá trình thực thi..

Hãy để Lùi trở lại ví dụ setTimeout của chúng tôi ở trên;

Khi chúng tôi chạy mã, dòng console.log đầu tiên được đẩy lên ngăn xếp và chúng tôi nhận được đầu ra gần như ngay lập tức, khi hết thời gian, bộ định thời được xử lý bởi trình duyệt và không phải là một phần của việc triển khai lõi V8, nó bị đẩy thay vào đó là API Web, giải phóng ngăn xếp để nó có thể thực hiện các hoạt động khác.

Trong khi thời gian chờ vẫn đang chạy, ngăn xếp sẽ chuyển sang dòng hành động tiếp theo và chạy console.log cuối cùng, điều này giải thích lý do tại sao chúng ta nhận được điều đó xuất ra trước khi đầu ra bộ đếm thời gian. Một khi bộ đếm thời gian được hoàn thành, một cái gì đó xảy ra. Console.log sau đó hẹn giờ xuất hiện một cách kỳ diệu trong ngăn xếp cuộc gọi một lần nữa!

Làm sao?

Vòng lặp sự kiện

Trước khi chúng ta thảo luận về vòng lặp sự kiện, trước tiên chúng ta hãy đi qua chức năng của hàng đợi nhiệm vụ.

Quay lại ví dụ hết thời gian của chúng tôi, khi API Web hoàn thành thực thi tác vụ, nó không chỉ tự động đẩy nó trở lại ngăn xếp cuộc gọi. Nó đi đến Hàng đợi nhiệm vụ. 

Hàng đợi là một cấu trúc dữ liệu hoạt động theo nguyên tắc First in First out, do đó, khi các tác vụ được đẩy vào hàng đợi, chúng sẽ thoát ra theo thứ tự đó. Các tác vụ đã được thực thi bởi API API Web, đang được đẩy vào Hàng đợi nhiệm vụ, sau đó quay lại Ngăn xếp cuộc gọi để in kết quả của chúng.

Nhưng chờ đã. VẬY LÀ GÌ???

Nguồn – https://youtu.be/8aGhZQkoFbQ

Vòng lặp sự kiện là một quá trình chờ cho Ngăn xếp cuộc gọi rõ ràng trước khi đẩy các cuộc gọi lại từ Hàng đợi nhiệm vụ sang Ngăn xếp cuộc gọi. Khi Stack rõ ràng, vòng lặp sự kiện sẽ kích hoạt và kiểm tra Hàng đợi nhiệm vụ cho các cuộc gọi lại có sẵn. Nếu có bất kỳ thứ gì, nó sẽ đẩy nó vào Ngăn xếp cuộc gọi, đợi cho ngăn xếp cuộc gọi được xóa lại và lặp lại quy trình tương tự.

Nguồn – https://www.quora.com/How-does-an-event-loop-workIm/Timothy-Maxwell

Sơ đồ trên biểu thị luồng công việc cơ bản giữa Vòng lặp sự kiện và Hàng đợi nhiệm vụ.

Phần kết luận

Mặc dù đây là một giới thiệu rất cơ bản, khái niệm lập trình không đồng bộ trong JavaScript cung cấp đủ thông tin chi tiết để hiểu rõ ràng những gì đang diễn ra dưới mui xe và cách JavaScript có thể chạy đồng thời và không đồng bộ chỉ bằng một luồng duy nhất.

JavaScript luôn theo yêu cầu và nếu bạn tò mò muốn tìm hiểu, tôi sẽ khuyên bạn nên kiểm tra điều này Khóa học của kẻ thù.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me