Hướng dẫn nodejs event loop - vòng lặp sự kiện nodejs
Giới thiệuEvent Loop là một trong những khái niệm cực kì quan trọng khi chúng ta tìm hiểu về Node.js. Show Tại sao nó lại quan trọng đến như vậy? và làm cách nào để Node.js có thể xử lý bất đồng bộ (asynchronous) và non-blocking I/O.làm cách nào để Node.js có thể xử lý bất đồng bộ (asynchronous) và non-blocking I/O.
Node.js là xử lý đơn luồng, nên nó sẽ chỉ làm một việc một lúc. Thực tế thì sự hạn chế này rất hữu dụng, nó sẽ giúp chúng ta đơn giản hóa rất nhiều cách mà chúng ta lập trình mà không phải lo về vấn đề tương tranh. Nhưng khi code chúng ta cần chú ý để tránh mọi thứ có thể chặn thread như là những request API đồng bộ hoặc vòng lặp vô hạn. Nói chung là trong hầu hết các trình duyệt đều có một event loop cho mỗi tab của trình duyệt để làm cho mọi quy trính xử lý cô lập với nhau và tránh một trang web có vòng lặp vô hạn hoặc xử lý nặng có thể chặn toàn bộ trình duyệt. Các Web Workers cũng chạy trong một vòng lặp riêng. Chúng ta chủ yếu cần quan tâm rằng code của chúng ta sẽ chạy trên một Event Loop riêng để tránh việc blocking event loop.blocking event loop. Blocking the event loopMột đoạn code Javascript mà mất quá nhiều thời gian để xử lý sẽ chặn việc thực thi thêm bất kỳ đoạn code Javascript nào trong trang, thậm chí sẽ chặn luôn cả luồng UI và người dùng không thể click chuột hay cuộn trang, v.v. Hầu như tất cả các I/O trong JS đều là non-blocking. Network request, filesystem, v.v. Việc bị blocking có thể coi là một exception, và đó là lý do vì sao JS dựa rất nhiều vào việc sử dụng callback, và gần đây hơn là sử dụng promises và aysnc/await. Call stackCall stack là một LIFO (Last In, First Out) queue.LIFO (Last In, First Out) queue. Event Loop sẽ liên tục kiểm tra call stack để xem có function cần thực thi hay không. Trong quá trình này, nó sẽ thêm bất kì function nào nó tìm thấy vào trong call stack và thực thi từng function một theo thứ tự.call stack để xem có function cần thực thi hay không. Trong quá trình này, nó sẽ thêm bất kì function nào nó tìm thấy vào trong call stack và thực thi từng function một theo thứ tự. Chúng ta hãy cùng xem cách mà Event Loop và call stack hoạt động qua một ví dụ đơn giản sau đây
Qua đoạn code trên, ta có thể thấy fucntion Event Loop thực thi những gì nó lấy ra từ call stack và việc này sẽ được lặp đi lặp lại cho đến khi call stack rỗng. Queuing function executionĐoạn code ở trên là một ví dụ đơn giản: Javascript sẽ thực thi những gì nó đọc được theo thứ tự. Bây giờ chúng ta cùng xem qua đoạn mã này nhé
Với những bạn mới làm quen với Javascript thì có thể sẽ cho rằng output của đoạn mã trên sẽ là
nhưng khi đoạn mã trên được thực thi thì sẽ lại thấy output không hề như vậy mà sẽ lại in ra như này mà sẽ lại in ra như này
Chúng ta hãy xem cách đoạn code trên thực thi qua ảnh sau đây Đây là thứ tự các bước mà đoạn mã của chúng ta được thực thi Vậy tại sao nó lại như vậy? The Event/Message QueueTrên tài liệu của Node.js thì gọi là Message Queue nhưng ở những tài liệu khác thì lại gọi là Event Queue. Mình có thử tìm hiểu thì hai thằng này tương đương nhau, chỉ khác cách gọi, với mình thì mình quen gọi là Event Queue hơn .Message Queue nhưng ở những tài liệu khác thì lại gọi là Event Queue. Mình có thử tìm hiểu thì hai thằng này tương đương nhau, chỉ khác cách gọi, với mình thì mình quen gọi là Event Queue hơn .Khi hàm Event Queue cũng là nơi mà các sự kiện do người dùng thực hiện như click, gõ phím hay fetch API sẽ được đẩy vào một hàng đợi và chờ đến khi được lấy ra và thực thi. cũng là nơi mà các sự kiện do người dùng thực hiện như click, gõ phím hay fetch API sẽ được đẩy vào một hàng đợi và chờ đến khi được lấy ra và thực thi. Như chúng ta đã biết thì Event Loop sẽ liên tục tìm kiếm trong call stack những gì cần thực thi cho đến khi call stack rỗng nhưng Event Loop sẽ không dừng ở đó, nó sẽ bắt đầu đọc tiếp Event Queue để nhặt ra những gì được nhét vào đó và lôi ra để thực thi. Chúng ta sẽ không phải ngồi đợi những hàm như
ES6 Job QueueECMAScript 2015 giới thiệu cho chúng ta về Job Queue, và được Promises sử dụng (cũng được giới thiệu trong ES6/ES2015). Nó là một cách để thực thi các hàm bất đồng bộ sớm nhất có thể, thay vì đẩy vào cuối cùng của call stack. Promises sẽ resolve trước khi hàm hiện tại kết thúc và sẽ được thực thi ngay sau hàm hiện tại. Nó giống như việc chúng ta đi chơi tàu lượn và phải đứng xếp hàng để đợi vậy: Event Queue sẽ xếp chúng ta vào cuối cùng của hàng và chúng ta sẽ phải đợi cho đến lượt của mình, còn Job Queue thì sẽ giống như một cái vé fastpass sẽ giúp chúng ta được đi ngay chuyến tàu lượn ngay sau khi chuyến trước kết thúc.
Đây chính là sự khác biệt giữa Promises (và async/await - được built dựa trên promises) và các hàm bất đồng bộ cũ khác như Tổng kếtVậy là qua bài viết này, mình cùng mọi người đã có thể hiểu hơn về Event Loop trong Node.js. Tham khảohttps://nodejs.dev/ http://www.ecma-international.org/ecma-262/6.0/#sec-jobs-and-job-queues https://developer.mozilla.org/vi/docs/Web/JavaScript/Reference/Global_Objects/Promise |