
Reverse Ajax, Phần 1: Giới thiệu về Comet
Ajax, Reverse Ajax và WebSockets
Ajax (Asynchronous JavaScript và XML), một kỹ thuật dành cho trình duyệt dựa trên JavaScript,
cho phép sử dụng một đoạn mã lệnh để đáp ứng các yêu cầu HTTP cho từng thành phần mà
không cần phải refresh lại toàn bộ trang web. Ajax đã được ứng dụng hơn 10 năm nay. Mặc dù
tên của nó có kèm theo XML, nhưng bạn có thể truyền tải bất cứ thứ gì trong một yêu cầu Ajax.
Dữ liệu được sử dụng phổ biến nhất là JSON, nó có cú pháp gần với cú pháp của JavaScript và
tiêu thụ ít băng thông hơn. Liệt kê 1 là ví dụ về một yêu cầu Ajax để lấy ra tên của một vùng địa
phương từ mã bưu chính của nó.
Liệt kê 1. Ví dụ về yêu cầu Ajax
var url = 'http://www.geonames.org/postalCodeLookupJSON?postalcode='
+ $('#postalCode').val() + '&country='
+ $('#country').val() + '&callback=?';
$.getJSON(url, function(data) {
$('#placeName').val(data.postalcodes[0].placeName);
});
Bạn có thể xem cách hoạt động của ví dụ trên trong file listing1.html có ở đây.
Về cơ bản Reverse Ajax là một khái niệm: có thể gửi dữ liệu từ máy chủ đến máy khách. Trong
một yêu cầu Ajax của HTTP tiêu chuẩn, dữ liệu được gửi đến máy chủ. Reverse Ajax có thể
được mô phỏng để tạo ra một yêu cầu Ajax, theo những cách cụ thể được nêu ra trong bài viết
này, do đó, máy chủ có thể gửi các sự kiện đến máy khách càng nhanh càng tốt (giao tiếp với độ
trễ thấp).
WebSockets, có kèm theo HTML5, là một kỹ thuật mới hơn. Nhiều trình duyệt đã hỗ trợ nó
(Firefox, Google Chrome, Safari và những trình duyệt khác). WebSockets tạo nên các kênh
truyền thông song song, hai chiều. Kết nối này được mở ra thông qua một yêu cầu HTTP được
gọi là WebSockets handshake với một số header đặc biệt. Kết nối này được duy trì và bạn có thể
viết và nhận dữ liệu bằng JavaScript, như thể bạn đang sử dụng một TCP socket nguyên bản.
WebSockets sẽ được trình bày trong phần 2 của loạt bài này.
Về đầu trang
Các kỹ thuật Reverse Ajax
Mục tiêu của kỹ thuật Reverse Ajax là giúp các máy chủ đẩy thông tin đến máy khách. Theo mặc
định các yêu cầu Ajax là không chính thống và chỉ có thể được bắt đầu từ máy khách đến máy
chủ. Bạn có thể vượt qua hạn chế này bằng cách sử dụng các kỹ thuật để mô phỏng truyền thông
đáp ứng giữa máy chủ và máy khách.

HTTP polling và JSONP polling
Polling bao gồm việc gửi một thông điệp từ phía máy khách đến máy chủ để yêu cầu một thông
tin dữ liệu nào đó. Thực ra đây chỉ là một yêu cầu HTTP của Ajax. Để có được các sự kiện từ
máy chủ càng sớm thì khoảng thời gian polling (thời gian giữa các yêu cầu) phải càng ngắn càng
tốt. Có một nhược điểm là: nếu khoảng thời gian này càng ngắn, trình duyệt của máy khách sẽ
đưa ra nhiều yêu cầu hơn, trong đó có những yêu cầu sẽ không trả về bất kỳ dữ liệu có ích nào
khiến cho băng thông bị hao tốn và xử lý tài nguyên vô ích.
Bảng thời gian trong Hình 1 cho thấy cách mà máy khách gửi các yêu cầu polling nhưng chẳng
có thông tin nào được trả về cả. Máy khách phải chờ đến lần polling tiếp theo để có được hai sự
kiện do máy chủ thu nhận được.
Hình 1. Reverse Ajax với việc polling của HTTP
Về bản chất, polling của JSONP giống như polling của HTTP. Tuy nhiên, có sự khác biệt ở chỗ
với JSONP bạn có thể đưa ra yêu cầu giữa các domain (các yêu cầu không có trong domain của
bạn). JSONP được dùng trong Liệt kê 1 để nhận về một tên địa phương từ một mã bưu chính.
Thường thì có thể nhận ra một yêu cầu JSONP bằng cách xem tham số gọi lại và nội dung trả về
của nó, đó chính là mã JavaScript có thể chạy được.
Để thực hiện polling trong JavaScript, bạn có thể sử dụng hàm setInterval để định thời gian
gửi các yêu cầu Ajax, như trong Liệt kê 2:
Liệt kê 2. Polling trong JavaScript
setInterval(function() {
$.getJSON('events', function(events) {
console.log(events);
});
}, 2000);

Đoạn mã demo kỹ thuật polling ở đây cho thấy phương pháp này tiêu thụ băng thông như thế
nào. Khoảng thời gian cho các lần polling ngắn nhưng có thể bạn sẽ nhận các kết quả trả về mà
chẳng có sự kiện (event) mới nào. Liệt kê 3 hiển thị kết quả của việc polling ở ví dụ mẫu.
Liệt kê 3. Kết quả của đoạn demo polling trong ví dụ mẫu
[client] checking for events...
[client] no event
[client] checking for events...
[client] 2 events
[event] At Sun Jun 05 15:17:14 EDT 2011
[event] At Sun Jun 05 15:17:14 EDT 2011
[client] checking for events...
[client] 1 events
[event] At Sun Jun 05 15:17:16 EDT 2011
Polling trong JavaScript có các ưu và nhược điểm.
Ưu điểm: Nó thực sự dễ thực hiện và không đòi hỏi bất kỳ tính năng đặc biệt nào ở phía
máy chủ. Nó cũng làm việc trong tất cả các trình duyệt.
Nhược điểm: Phương pháp này hiếm khi được sử dụng vì nó không hề linh động. Hãy
tưởng tượng, giả sử có 100 máy khách, trong đó mỗi máy gửi các yêu cầu polling trong 2
giây thì số lượng băng thông và tài nguyên bị hao tốn như thế nào, ở đây 30% yêu cầu
được trả về không hề có chút dữ liệu.
Piggyback
Piggyback polling là một phương pháp thông minh hơn nhiều so với polling đơn thuần vì nó có
xu hướng loại bỏ tất cả các yêu cầu không cần thiết (các yêu cầu không trả về dữ liệu nào).
Không cần định sẵn một khoảng thời gian interval nào cả; yêu cầu sẽ được gửi đi khi máy khách
cần gửi một yêu cầu đến máy chủ. Sự khác biệt nằm ở cách phản hồi được chia thành hai phần:
phản hồi với dữ liệu được yêu cầu và các sự kiện từ máy chủ. Hình 2 chính là ví dụ.
Hình 2. Reverse Ajax với Piggyback polling

Khi thực hiện kỹ thuật Piggyback, thông thường tất cả các yêu cầu Ajax gửi đến máy chủ có thể
được trả về một phản hồi hỗn hợp. Ví dụ mẫu về cách thực hiện kỹ thuật này có ở đây và trong
Liệt kê 4 dưới đây.
Liệt kê 4. Ví dụ mẫu về mã piggyback
$('#submit').click(function() {
$.post('ajax', function(data) {
var valid = data.formValid;
// process validation results
// then process the other part of the response (events)
processEvents(data.events);
});
});
Liệt kê 5 hiển thị kết quả khi sử dụng phương pháp piggyback.
Liệt kê 5. Kết quả piggyback
[client] checking for events...
[server] form valid ? true
[client] 4 events
[event] At Sun Jun 05 16:08:32 EDT 2011
[event] At Sun Jun 05 16:08:34 EDT 2011
[event] At Sun Jun 05 16:08:34 EDT 2011
[event] At Sun Jun 05 16:08:37 EDT 2011
Bạn có thể thấy kết quả của việc kiểm tra hợp lệ một khuôn mẫu (form validation) và các sự kiện
được thêm vào phản hồi. Một lần nữa, phương pháp này có những ưu và nhược điểm.
Ưu điểm: Không có các yêu cầu nào trả về mà không có dữ liệu, vì máy khách kiểm soát
khi nó gửi các yêu cầu, nên bạn tiêu thụ ít tài nguyên hơn. Nó cũng làm việc trong tất cả
các trình duyệt và không yêu cầu các tính năng đặc biệt ở phía máy chủ.
Nhược điểm: Bạn sẽ không biết khi nào mà các sự kiện ở phía máy chủ được gửi tới máy
khách vì nó đòi hỏi phải có một hành động từ phía máy khách để yêu cầu chúng.
Về đầu trang
Comet
Reverse Ajax với kỹ thuật polling hay piggyback cũng còn rất hạn chế: vì nó không co giãn và
không cung cấp khả năng giao tiếp với độ trễ thấp (tức là các sự kiện phải được gửi đến trình
duyệt ngay khi chúng đến máy chủ). Comet là một mô hình ứng dụng web, ở đây một yêu cầu
được gửi đến máy chủ và vẫn tiếp tục trong một thời gian dài cho đến khi hết giờ hoặc xuất hiện
một sự kiện từ máy chủ. Khi yêu cầu này được hoàn thành thì sẽ có một yêu cầu Ajax khác được

gửi đi để chờ các sự kiện khác từ máy chủ. Với Comet, các máy chủ web có thể gửi dữ liệu cho
máy khách mà cần phải có một yêu cầu cụ thể nào.
Ưu điểm lớn của Comet ở chỗ mỗi máy khách luôn có một liên kết giao tiếp đến máy chủ. Máy
chủ có thể đẩy các sự kiện vào các máy khách bằng cách thực hiện commit (hay hoàn thành)
ngay lập tức các phản hồi ngay khi chúng đến hoặc thậm chí nó có thể tích lũy và gửi một lần. Vì
một yêu cầu được mở trong một thời gian dài, nên cần có các tính năng đặc biệt ở phía máy chủ
để xử lý tất cả những long-lived này (long-lived requets - các yêu cầu có thời gian sống lâu).
Hình 3 là ví dụ. (Phần 2 của loạt bài này sẽ giải thích các ràng buộc máy chủ chi tiết hơn).
Hình 3. Reverse Ajax với Comet
Các cách thực hiện của Comet có thể được chia thành hai loại: một loại sử dụng chế độ
streaming và một loại khác sử dụng long polling.
Về đầu trang
Comet sử dụng kỹ thuật HTTP Streaming
Trong chế độ streaming, một kết nối được mở liên tục. Sẽ chỉ có một yêu cầu long-lived (#1
trong Hình 3) do mỗi sự kiện đến phía máy chủ được gửi đi thông qua cùng một kết nối. Do đó,
nó đòi hỏi ở phía máy khách phải có cơ chế phân chia các phản hồi đến từ cùng một nguồn kết
nối đó. Về mặt kỹ thuật, hai kỹ thuật phổ biến về streaming là Forever Iframes (Các IFrame ẩn)
và tính năng đa-phần (multi-part) của đối tượng XMLHttpRequest được sử dụng để tạo ra các
yêu cầu Ajax trong JavaScript.
Forever Iframes

