Cái Duyên Với Ajax - nói dối e blog

Cái Duyên Với Ajax

Chơi một chút với ajax.

Chơi một chút với ajax.

Một buổi tối rảnh rỗi, tôi quyết định thử sức với công nghệ Ajax. Câu chuyện bắt đầu từ việc mấy đồng nghiệp trong nhóm chat bàn tán về việc không tìm được bạn chơi bridge. Các trang web hiện có đều yêu cầu cài đặt phần mềm hoặc đăng ký phức tạp. Tôi liền đề xuất: “Sao không làm một trang web chơi bridge không cần cài đặt, không cần đăng ký nhỉ?” Thế là hành trình bắt đầu…

Từ lâu tôi đã nghe đồn Ajax có thể giúp trình duyệt “giao tiếp” với server mà không cần tải lại trang. Dù chưa từng làm web, chỉ mới từng viết một cái guestbook bằng PHP cách đây vài năm, tôi vẫn tự tin rằng chỉ cần học một buổi chiều và thức trắng một đêm là xong. Ai ngờ, nửa tuần trôi qua, hai đêm thức trắng trôi qua, dự án vẫn chưa hoàn thành. Mai lại phải đi công tác nên đành gác lại.

Hiểu sai về web

Trước khi bắt tay vào làm, tôi nhớ lại vài kiến thức rời rạc:

  • Web khác biệt hoàn toàn với game online mà tôi đang làm. Web chủ yếu dùng HTTP - giao thức kết nối ngắn, mỗi lần gửi request rồi nhận response.
  • Để giữ trạng thái giữa các request, có thể dùng session key lưu trong cookie hoặc URL. Nhưng trình duyệt cho phép người dùng refresh bất kỳ lúc nào, thậm chí gửi nhiều request song song. Nói cách khác, giao tiếp giữa browser và server giống như giao thức UDP - không đảm bảo thứ tự, không đảm bảo xử lý hết, thậm chí cho phép nhận lại request cũ.

Bài toán “ngược”

Vấn đề lớn nhất là server không thể chủ động gửi dữ liệu về client. Ajax giải quyết bằng cách dùng timer để client liên tục “hỏi” server: “Có gì mới không?”. Ngày xưa người ta dùng iframe ẩn để làm việc này, giờ thì XMLHttpRequest giúp đơn giản hóa quá trình.

Chọn công cụ: Lua bất ngờ lên ngôi

Tôi quyết định dùng Lua - ngôn ngữ quen thuộc nhất. May mắn thay, có bộ công cụ Kepler cho phép phát triển web bằng Lua với gói cài đặt chỉ 700KB. Cài đặt chưa đầy 5 phút, nhưng khi bắt tay vào code mới thấy mọi thứ không đơn giản.

Đau đầu với session

Để lưu trạng thái ván bài, tôi phát hiện module session của Kepler có vấn đề: không hỗ trợ khóa dữ liệu! Khi 4 người chơi cùng một bàn, dữ liệu dễ bị ghi đè. Tôi thử dùng version number để kiểm soát xung đột nhưng quá phức tạp. Cuối cùng đành chấp nhận rủi ro, hy vọng coroutine của Lua sẽ giúp xử lý đúng thứ tự.

Khám phá rings và state

Kepler có tính năng rings cho phép tạo các “slave state” từ một “master state” chính. Điều này giúp quản lý bộ nhớ hiệu quả, tránh rò rỉ tài nguyên. Tôi quyết định lưu toàn bộ trạng thái ván bài trong master state để dễ truy xuất.

Vấp váp với redirect

Một bug bất ngờ: hàm cgilua.redirect không hoạt động. Hóa ra server tự ý gửi mã 204 thay vì 301/302. Đọc code sửa lỗi này khiến tôi thức trắng đêm, nhưng cũng học được cách Kepler xử lý khác biệt giữa Lua 5.0 và 5.1 qua cơ chế “code generation”.

Giải pháp cho trạng thái ván bài

Tôi chọn phương án đơn giản: mỗi request đều gửi toàn bộ trạng thái bàn chơi kèm version number. Dù tốn băng thông nhưng dễ triển khai. May mắn là chỉ cần vài giờ là hoàn thành giao diện phòng chơi và logic chia bài.

Bài học từ trình duyệt

IE khiến tôi “sốc” khi cache kết quả request động (URL có dấu ?). Phải thêm header đặc biệt mới khắc phục được. Đây là lời nhắc nhở về sự khác biệt giữa lý thuyết và thực tế khi làm web.

Tương lai của dự án

  • Không cần đăng ký: Tạo UID duy nhất lưu trong cookie
  • Tự do vào phòng: Gửi URL cho bạn bè là cùng chơi
  • Không phân quyền: Ai cũng có thể ngồi bất kỳ vị trí nào (Đông/Nam/Tây/Bắc + khán giả)
  • Phiên bản di động: Có thể làm bản không dùng Ajax để tương thích điện thoại

Kết luận

Lua chứng minh sức mạnh qua dự án này. Nếu ai nghi ngờ tiềm năng của Lua trong phát triển web, hãy xem Sputnik - hệ thống wiki chỉ với 2000 dòng code Lua. Dù chưa hoàn thành, dự án này đã cho tôi nhiều bài học quý giá về sự khác biệt giữa lý thuyết và thực tế trong phát triển web.

0%