Chính xác thì đánh dấu vòng lặp sự kiện Node.js là gì?


83

Tôi đã tìm hiểu sâu hơn về bên trong của kiến ​​trúc Node.js và một thuật ngữ tôi thấy xuất hiện nhiều là "đánh dấu" như trong "đánh dấu tiếp theo của vòng lặp sự kiện" hoặc hàm nextTick () .

Những gì tôi chưa thấy là một định nghĩa chắc chắn về chính xác "tích tắc" là gì. Dựa trên nhiều bài báo khác nhau ( chẳng hạn như bài báo này ), tôi đã có thể ghép một khái niệm lại với nhau trong đầu, nhưng tôi không chắc nó chính xác đến mức nào.

Tôi có thể nhận được mô tả chính xác và chi tiết về dấu tích vòng lặp sự kiện Node.js không?


vì "vòng lặp" của nó, nó có nghĩa là "lần tiếp theo nó lặp", vì vậy hãy đánh dấu vào toàn bộ vòng lặp của nó, nó kết thúc khi không có sự kiện nào được kích hoạt và nodejs đã lặp lại tất cả để kiểm tra xem có sự kiện nào được kích hoạt hay không, "nextTick" có nghĩa là tiếp theo vòng lặp sau vòng lặp hiện tại.
Gntem

Câu trả lời:


155

Hãy nhớ rằng mặc dù JavaScript là một luồng, tất cả I / O của nút và các lệnh gọi tới API gốc đều không đồng bộ (sử dụng cơ chế dành riêng cho nền tảng) hoặc chạy trên một luồng riêng biệt. (Tất cả điều này được xử lý thông qua libuv.)

Vì vậy, khi có dữ liệu có sẵn trên một socket hoặc một hàm API gốc được trả về, chúng ta cần một cách đồng bộ hóa để gọi hàm JavaScript quan tâm đến sự kiện cụ thể vừa xảy ra.

Sẽ không an toàn nếu chỉ gọi hàm JS từ chuỗi nơi sự kiện gốc đã xảy ra vì những lý do tương tự mà bạn gặp phải trong một ứng dụng đa luồng thông thường - điều kiện chủng tộc, quyền truy cập bộ nhớ không nguyên tử, v.v.

Vì vậy, những gì chúng tôi làm là đặt sự kiện vào hàng đợi một cách an toàn theo chuỗi. Trong mã ảo giác đơn giản hóa, một cái gì đó như:

lock (queue) {
    queue.push(event);
}

Sau đó, quay lại chuỗi JavaScript chính (nhưng ở phía C của mọi thứ), chúng tôi làm một cái gì đó như:

while (true) {
    // this is the beginning of a tick

    lock (queue) {
        var tickEvents = copy(queue); // copy the current queue items into thread-local memory
        queue.empty(); // ..and empty out the shared queue
    }

    for (var i = 0; i < tickEvents.length; i++) {
        InvokeJSFunction(tickEvents[i]);
    }

    // this the end of the tick
}

Các while (true)(mà không thực sự tồn tại trong mã nguồn của nút, điều này là hoàn toàn minh họa) đại diện cho vòng lặp sự kiện . Bên trong forgọi hàm JS cho mỗi sự kiện có trong hàng đợi.

Đây là một đánh dấu: sự gọi đồng bộ của không hoặc nhiều hàm gọi lại được liên kết với bất kỳ sự kiện bên ngoài nào. Khi hàng đợi được làm trống và chức năng cuối cùng trả về, dấu tích kết thúc. Chúng tôi quay lại phần đầu (đánh dấu tiếp theo) và kiểm tra các sự kiện đã được thêm vào hàng đợi từ các chuỗi khác trong khi JavaScript của chúng tôi đang chạy .

Điều gì có thể thêm những thứ vào hàng đợi?

  • process.nextTick
  • setTimeout/setInterval
  • I / O (nội dung từ fs, netv.v.)
  • cryptocác chức năng chuyên sâu về bộ xử lý như luồng tiền điện tử, pbkdf2 và PRNG (thực sự là một ví dụ về ...)
  • bất kỳ mô-đun gốc nào sử dụng hàng đợi công việc libuv để làm cho các lệnh gọi thư viện C / C ++ đồng bộ trông không đồng bộ

2
Vâng, bạn đã đóng đinh điều này. Việc sao chép hàng đợi và chạy qua tất cả các sự kiện trên bản sao là điều tôi đặc biệt băn khoăn. Bây giờ có rất nhiều ý nghĩa mặc dù. Cảm ơn.
d512

Đây có phải là thuật ngữ nổi tiếng "Mẫu lặp lại không đồng bộ" không?
Stef

1
@sanjeev, bạn hiểu "công việc thường xuyên" nghĩa là gì? Điều duy nhất mà một ứng dụng JavaScript đang thực hiện là các sự kiện quy trình.
josh3736

2
Tôi muốn thêm rằng trong 0.10.x setImmediatecũng sẽ xếp hàng một hàm.
DanielKhan

1
Đánh dấu có nghĩa là giai đoạn vòng lặp sự kiện?
faressoft

10

Một câu trả lời đơn giản hơn cho những người mới sử dụng JavaScript:

Điều đầu tiên cần hiểu là JavaScript là một "môi trường đơn luồng". Điều này đề cập đến hành vi của JavaScript khi thực thi từng khối mã của bạn từ "vòng lặp sự kiện" trên một chuỗi duy nhất. Dưới đây là một cách xử lý thô sơ của vòng lặp sự kiện được lấy từ cuốn sách ydkJS của Kyle Simpson và sau đó là lời giải thích:

// `eventLoop` is an array that acts as a queue (first-in, first-out)
var eventLoop = [ ];
var event;

// keep going "forever"
while (true) {
    // perform a "tick"
    if (eventLoop.length > 0) {
        // get the next event in the queue
        event = eventLoop.shift();

        // now, execute the next event
        try {
            event();
        }
        catch (err) {
            reportError(err);
        }
    }
}

Vòng lặp while đầu tiên mô phỏng vòng lặp sự kiện. Đánh dấu là xác định giá trị của một sự kiện từ "hàng đợi vòng lặp sự kiện" và việc thực hiện sự kiện đã nói.

Vui lòng xem phản hồi của 'Josh3796' để được giải thích chi tiết hơn về những gì xảy ra trong quá trình xác định giá trị và thực hiện một sự kiện.

Ngoài ra, tôi khuyên bạn nên đọc sách của Kyle Simpson cho những ai muốn hiểu sâu sắc về JavaScript. Nó hoàn toàn miễn phí và mã nguồn mở và có thể được tìm thấy tại liên kết này: https://github.com/getify/You-Dont-Know-JS

Phần cụ thể tôi đã tham khảo có thể được tìm thấy tại đây: https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/sync-async/ch1.md


1

Cách đánh dấu Event Loop rất đơn giản và ngắn gọn là:

Nó được sử dụng bởi cơ chế nội bộ của nút, nơi khi tập hợp các yêu cầu trên hàng đợi được xử lý thì đánh dấu được bắt đầu, biểu thị việc hoàn thành một nhiệm vụ


bạn có thể cung cấp một số nguồn cho câu trả lời của bạn xin vui lòng?
Kick Buttowski
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.