JavaScript xử lý các phản hồi AJAX trong nền như thế nào?


139

Vì JavaScript chạy trong một luồng duy nhất, sau khi yêu cầu AJAX được thực hiện, điều gì thực sự xảy ra trong nền? Tôi muốn có một cái nhìn sâu sắc hơn về điều này, bất cứ ai có thể làm sáng tỏ?



3
Mã JavaScript là một luồng đơn (trừ nhân viên web), nhưng không phải trình duyệt đang chạy công cụ JavaScript ...
Juan Mendes

@JuanMendes JavaScript có chạy trong một luồng trong khi Hàng đợi sự kiện chạy trong một luồng khác không?
Shaun Luttin

1
@ShaunLuttin Không, hàng đợi sự kiện là thứ khởi đầu cho JavaScript
Juan Mendes

Câu trả lời:


213

Bên dưới trang bìa, javascript có một hàng đợi sự kiện. Mỗi khi một chuỗi thực thi javascript kết thúc, nó sẽ kiểm tra xem liệu có một sự kiện nào khác trong hàng đợi để xử lý hay không. Nếu có, nó kéo nó ra khỏi hàng đợi và kích hoạt sự kiện đó (ví dụ như nhấp chuột chẳng hạn).

Mạng mã gốc nằm dưới lệnh gọi ajax sẽ biết khi nào phản hồi ajax được thực hiện và một sự kiện sẽ được thêm vào hàng đợi sự kiện javascript. Làm thế nào mã gốc biết khi nào cuộc gọi ajax được thực hiện tùy thuộc vào việc thực hiện. Nó có thể được thực hiện với các luồng hoặc nó cũng có thể là do sự kiện tự điều khiển (nó không thực sự quan trọng). Điểm quan trọng của việc triển khai là khi phản hồi ajax được thực hiện, một số mã gốc sẽ biết nó đã được thực hiện và đưa một sự kiện vào hàng đợi JS.

Nếu không có Javascript nào đang chạy vào thời điểm đó, sự kiện sẽ được kích hoạt ngay lập tức sẽ chạy trình xử lý phản hồi ajax. Nếu một cái gì đó đang chạy vào thời điểm đó, thì sự kiện sẽ được xử lý khi chuỗi thực thi javascript hiện tại kết thúc. Không cần phải có bất kỳ cuộc bỏ phiếu nào bởi công cụ javascript. Khi một đoạn Javascript kết thúc thực thi, công cụ JS chỉ kiểm tra hàng đợi sự kiện để xem liệu có gì khác cần chạy không. Nếu vậy, nó sẽ bật sự kiện tiếp theo ra khỏi hàng đợi và thực thi nó (gọi một hoặc nhiều hàm gọi lại được đăng ký cho sự kiện đó). Nếu không có gì trong hàng đợi sự kiện, thì trình thông dịch JS có thời gian rảnh (bộ sưu tập rác hoặc không hoạt động) cho đến khi một số tác nhân bên ngoài đặt một thứ khác vào hàng đợi sự kiện và đánh thức lại nó.

Bởi vì tất cả các sự kiện bên ngoài đều đi qua hàng đợi sự kiện và không có sự kiện nào được kích hoạt trong khi javascript thực sự đang chạy một thứ khác, nên nó vẫn duy trì một luồng.

Dưới đây là một số bài viết về các chi tiết:


Cảm ơn vì điều đó. Tôi nghi ngờ đây là trường hợp, nhưng tốt để biết chắc chắn. Tôi có một vòng lặp for, trong đó tôi gửi rất nhiều yêu cầu 'ajax'. Trong trình xử lý của tôi (đối với mỗi yêu cầu - được trả lại theo thứ tự tùy ý) tôi chạy một số mã có thể mất một thời gian. Tốt để biết điều này chắc chắn nên làm việc.
iPadDeveloper2011

4
@telandor - các sự kiện được chạy theo thứ tự FIFO (có thể có một số trường hợp ngoại lệ, nhưng mục đích là FIFO). Một số sự kiện được đối xử hơi khác nhau. Ví dụ: các sự kiện mousemove không chồng chất trong hàng đợi (có thể vì chúng có thể dễ dàng tràn qua hàng đợi). Khi chuột di chuyển và một sự kiện mousemove đã có trong hàng đợi và không có sự kiện nào mới hơn trong hàng đợi, nó được cập nhật với vị trí mới nhất thay vì một sự kiện mới được thêm vào. Tôi đoán rằng các sự kiện hẹn giờ khoảng thời gian có lẽ cũng được xử lý đặc biệt để tránh chúng chồng chất trong hàng đợi.
jfriend00

2
@telandor - bạn cần giải thích gì thêm? Đó là FIFO. Tôi đã thêm một vài bài viết tham khảo cho câu trả lời của tôi. Các vụ hành quyết duy nhất đến FIFO mà tôi biết là các sự kiện được kích hoạt ngay lập tức. Bạn gọi .focus()một mục và điều đó sẽ kích hoạt một vài sự kiện khác, chẳng hạn như sự kiện "làm mờ" trên mục đó với trọng tâm. Sự kiện mờ đó xảy ra đồng bộ và không đi qua hàng đợi sự kiện nên nó sẽ xảy ra ngay trước những thứ khác có thể có trong hàng đợi sự kiện. Trong thực tế, tôi chưa bao giờ thấy điều này là một mối quan tâm thực tế.
jfriend00

2
@telandor - Không có nhiều hàng đợi cho mỗi tài liệu trình duyệt. Có một hàng đợi và mọi thứ đều đi vào / ra. Vì vậy, thời gian chờ và phản hồi ajax và các sự kiện chuột và sự kiện bàn phím đều đi trong cùng một hàng đợi. Bất cứ ai được đưa vào hàng đợi trước sẽ được chạy trước.
jfriend00

1
@CleanCrispCode - Thx. Tôi đã thêm nó như một tài liệu tham khảo hữu ích cho câu trả lời của tôi.
jfriend00

16

Bạn có thể tìm thấy ở đây một tài liệu rất đầy đủ về xử lý các sự kiện trong javascript.
Nó được viết bởi một anh chàng làm việc về việc triển khai javascript trong Opera Browser.

Chính xác hơn, hãy xem các tiêu đề: "Dòng sự kiện", "Hàng đợi sự kiện" và "Sự kiện không dành cho người dùng": bạn sẽ biết rằng:

  1. Javascript chạy trong một luồng duy nhất cho mỗi tab hoặc cửa sổ trình duyệt.
  2. Các sự kiện được xếp hàng và thực hiện tuần tự.
  3. XMLHttpRequest được điều hành bởi việc triển khai và các cuộc gọi lại được chạy bằng hàng đợi sự kiện.

Lưu ý: Liên kết ban đầu là: liên kết , nhưng hiện đã chết.


1

Tôi muốn giải thích một chút, liên quan đến việc thực hiện ajax được đề cập trong câu trả lời.

Mặc dù thực thi Javascript (thông thường) không đa luồng - như đã lưu ý trong các câu trả lời ở trên - tuy nhiên , việc xử lý thực sự AJAX responses(cũng như xử lý yêu cầu) không phải là Javascript và thông thường - - đa luồng. (xem triển khai nguồn crom của XMLHttpRequest mà chúng tôi sẽ thảo luận ở trên)

và tôi sẽ giải thích, hãy lấy đoạn mã sau:

var xhr = new XMLHttpRequest();

var t = Date.now;
xhr.open( "GET", "https://swx.cdn.skype.com/shared/v/1.2.15/SkypeBootstrap.min.js?v="+t(), true );

xhr.onload = function( e ) {
		console.log(t() + ': step 3');
    
    alert(this.response.substr(0,20));
};
console.log(t() + ': step 1');
xhr.send();
console.log(t() + ': step 2');

after an AJAX request is made(- sau bước 1), sau đó trong khi mã js của bạn tiến hành thực thi (bước 2 và sau đó), trình duyệt bắt đầu công việc thực sự của: 1. định dạng yêu cầu tcp 2. mở ổ cắm 3. gửi tiêu đề 4. bắt tay 5. gửi cơ thể 6. phản hồi chờ đợi 7. đọc tiêu đề 8. đọc cơ thể, vv tất cả việc thực hiện này thường được chạy trong một luồng khác song song với thực thi mã js của bạn. ví dụ, việc triển khai crom được đề cập sử dụng Trình tải có thể chuyển đổi đi vào, (bạn cũng có thể có một số ấn tượng bằng cách xem tab mạng của tải trang, bạn sẽ thấy một số yêu cầu đồng thời).

để kết luận, tôi sẽ nói rằng - ít nhất - hầu hết các hoạt động I / O của bạn có thể được thực hiện đồng thời / không đồng bộ (và bạn có thể tận dụng lợi thế này bằng cách chờ đợi chẳng hạn). nhưng tất cả các tương tác với các hoạt động đó (việc phát hành, thực hiện gọi lại js) đều đồng bộ.

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.