2016-02-09 9 views
5

Hãy xem ví dụ sau:Hàng đợi sự kiện Javascript có phải là FIFO đơn giản hay không?

function A() { console.log('A'); } 
function B() { console.log('B'); } 
// and then i setTimeout(fn, 0) both of them 
setTimeout(A, 0); 
setTimeout(B, 0); 

Có guarantied rằng B sẽ ngay lập tức chạy sau A?
Trình duyệt có thể thêm một tác vụ khác vào hàng đợi giữa AB không?

lưu ý: không có chức năng nào trong số A hoặc B đang thêm bất kỳ tác vụ mới nào vào vòng lặp sự kiện.

var callbacks = []; 
// then add a bunch of callbacks ... (none adds events to event queue) 
//case 1: 
callbacks.forEach(cb => setTimeout(cb,0)) 
//case 2: 
setTimeout(function() { 
    callbacks.forEach(cb => cb()); 
},0); 

Có bất kỳ sự khác biệt trong thứ tự thực hiện của callbacks trong case 1 vs case 2?

+0

câu trả lời đơn giản: không có, không có đảm bảo. Bởi vì hàng đợi này được sử dụng bởi rất nhiều thứ khác ngoài JS engine. –

+0

có được sử dụng đồng thời không? và nó có thể là một sự kiện từ 'DOM' được đặt vào hàng đợi trong khi một phần của js đang chạy? (không phải là chủ đề duy nhất của js? và các tập lệnh js chạy dài ngừng đóng băng trình duyệt?) –

Trả lời

3

Có guarantied rằng B sẽ ngay lập tức chạy sau khi A?

Không ngay, không, nhưng nó đảm bảo rằng B sẽ chạy sau A. Chi tiết đầy đủ in the spec, nhưng trong ngắn hạn, điều này được giải quyết cụ thể trong timer initialization steps mà nói trong phần:

Chờ cho đến khi bất kỳ lời gọi của thuật toán này có bối cảnh cùng một phương pháp, mà bắt đầu trước thế này, và có thời gian chờ là bằng hoặc nhỏ hơn cái này, đã hoàn thành.

Tùy chọn, đợi thêm khoảng thời gian xác định tác nhân người dùng.

Sắp xếp công việc tác vụ.

... trong đó nhiệm vụ là nhiệm vụ gọi lại cuộc gọi bạn đã cung cấp setTimeout.

Hàng đợi nhiệm vụ bắt buộc phải chạy theo thứ tự và do đó A sẽ chạy trước B trên trình duyệt tuân thủ.

Lưu ý rằng điều này được đảm bảo bởi vì chúng được xếp hàng đợi theo cùng ngữ cảnh phương pháp (xem thông số kỹ thuật để biết chi tiết về điều đó có nghĩa là gì).

Trình duyệt có thể thêm nhiệm vụ khác vào hàng đợi giữa A và B không?

Có. Trình duyệt có thể được đa luồng và xếp hàng một nhiệm vụ cho một số thứ khác (một tin nhắn từ một nhân viên web, vv) ở giữa xếp hàng các nhiệm vụ cho AB. Trong trường hợp đó, bạn sẽ thấy A chạy, sau đó trình xử lý của bạn cho tác vụ khác (xử lý thư từ nhân viên web hoặc bất kỳ công việc nào), sau đó B.

1

Chúng sẽ luôn kích hoạt đúng thứ tự, A rồi B. Tuy nhiên, chúng có thể không lửa liên tiếp.

Thực tế, the specification says các lần gọi lại thời gian chờ thậm chí không được đặt trên hàng đợi thực hiện cho đến khi bộ đếm thời gian trôi qua, có thể bị trì hoãn thêm - thời gian chờ bạn chỉ định là tối thiểu.

+0

Có thể thực hiện một tác vụ khác là 'C' chạy giữa' A' và 'B'? –

+0

'chúng có thể không cháy liên tục' ... nhưng thời gian chờ là 0 ... –

+0

Có, có thể. Trong khi không, bản thân động cơ được đa luồng và có thể nhận một sự kiện khác để xếp hàng giữa 'A' được thêm vào hàng đợi và' B' được thêm vào hàng đợi. –

-1

Yep, nếu yo thử điều này:

function A() { console.log('A'); } 
function B() { console.log('B'); } 
function C() { while(1) { console.log('C'); } } 
// and then i setTimeout(fn, 0) both of them 
setTimeout(A, 0); 
setTimeout(C, 0); 
setTimeout(B, 0); 

Bạn sẽ thấy rằng các chức năng C có một vòng lặp vô hạn, vì vậy nó không bao giờ là chức năng được thực hiện là B. Điều này là do chức năng truyền cho các nhiệm vụ/sự kiện danh sách và chạy như những kết thúc. Điều này liên quan đến danh sách sự kiện SetTimeout có một cách làm việc cụ thể. nhưng, nếu bạn yêu cầu.

Mặt khác, nếu bạn hỏi xem trường hợp đó có được thực hiện trước hay không, tiếp theo là B, câu trả lời không đảm bảo xảy ra vì chúng không phải là sự kiện duy nhất có thể chạy.

Các vấn đề liên quan