Phỏng vấn vị trí Node.js Backend Developer không chỉ đòi hỏi bạn biết viết code chạy được, mà còn cần hiểu sâu về kiến trúc bên dưới như Event Loop, Async/Await và Memory Management. Bài viết này sẽ chỉ ra những lỗi diễn đạt khiến bạn mất điểm oan, cùng bí quyết trả lời ghi điểm từ senior developer.
1. Hiểu sai hoặc trả lời hời hợt về cơ chế Event Loop
Khi được hỏi 'Node.js hoạt động như thế nào?', nhiều ứng viên thường trả lời ngắn gọn rằng 'Node.js dùng single-thread nên nó nhanh'. Câu trả lời này quá bề mặt và không thuyết phục được phỏng vấn viên cấp cao.
Thực tế, Node.js chạy JavaScript trên một luồng đơn nhưng các thao tác I/O nặng được ủy quyền cho thư viện C++ libuv thông qua Thread Pool. Việc không nắm rõ các pha trong Event Loop (như timers, poll, check) sẽ khiến bạn lúng túng khi gặp các câu hỏi tình huống về thứ tự thực thi code bất đồng bộ.
- Tránh nói: Node.js hoàn toàn là đơn luồng nên không lo xung đột dữ liệu.
- Nên nói: Node.js sử dụng Single-threaded Event Loop kết hợp với Libuv Thread Pool để xử lý bất đồng bộ, giúp tối ưu hóa các tác vụ I/O-bound mà không phải tốn tài nguyên tạo luồng riêng cho từng request.
2. Lạm dụng các hàm Synchronous làm block Event Loop
Một lỗi kinh điển khác là ứng viên thản nhiên đề xuất dùng các hàm đồng bộ như fs.readFileSync hoặc crypto.pbkdf2Sync trong môi trường production chỉ vì 'code ngắn và dễ viết'.
Trong Node.js, bất kỳ thao tác chặn nào (blocking) trên luồng chính đều làm tê liệt toàn bộ ứng dụng, ảnh hưởng đến mọi request đang kết nối tới server. Phỏng vấn viên cực kỳ dị ứng với những ai xem nhẹ tính bất đồng bộ của môi trường này.
- Tránh nói: Em dùng readFileSync cho tiện ở bước khởi động ứng dụng.
- Nên nói: Luôn ưu tiên sử dụng Async/Await hoặc Streams để xử lý file và dữ liệu lớn, đảm bảo Event Loop không bị block nhằm duy trì high availability cho hệ thống.
3. Xử lý lỗi (Error Handling) hời hợt với Async/Await
Viết code async/await mà quên mất try...catch hoặc bỏ sót việc bắt unhandledRejection là điểm trừ rất nặng. Nhiều ứng viên nghĩ rằng chỉ cần viết code chạy được là đủ, bỏ qua việc hệ thống sẽ ứng xử thế nào khi database sập hoặc network timeout.
Nhà tuyển dụng luôn đánh giá cao những lập trình viên có tư duy phòng thủ (defensive programming), biết cách bắt lỗi tập trung và không làm crash ứng dụng ngầm.
- Tránh nói: Em cứ throw error lên trên rồi để Express tự lo.
- Nên nói: Xây dựng global error handling middleware, kết hợp try-catch cẩn thận cho từng async route handler hoặc sử dụng các utility wrapper để bắt lỗi Promise tự động.
4. Mơ hồ về Memory Leaks và Garbage Collection
Khi được hỏi về nguyên nhân gây rò rỉ bộ nhớ (memory leak) trong Node.js, câu trả lời quen thuộc của nhiều bạn là 'do tốn RAM' hoặc 'do JavaScript tự dọn dẹp rồi'.
Thực tế, V8 Engine có cơ chế Garbage Collection nhưng memory leak vẫn xảy ra phổ biến do biến toàn cầu (global variables), closures giữ tham chiếu không cần thiết, hoặc event listeners không được gỡ bỏ đúng cách.
- Tránh nói: V8 tự động quản lý bộ nhớ nên tụi em không cần bận tâm về memory leak.
- Nên nói: Em thường dùng clinic.js hoặc heapdump để phân tích memory leak, chú ý dọn dẹp event listener và tránh lưu trữ dữ liệu vô hạn trong các biến global hoặc closure.
5. Thiết kế cấu trúc dự án và gom business logic vào Controller
Trong các câu hỏi về system design hoặc code structure, lỗi phổ biến là dồn toàn bộ logic xử lý vào file Controller hoặc viết code dạng 'spaghetti code' không phân tầng.
Điều này cho thấy ứng viên thiếu kinh nghiệm làm việc với các codebase lớn, khó maintain và khó scale.
- Tránh nói: Em gom hết logic gọi database vào controller cho gọn.
- Nên nói: Áp dụng Separation of Concerns bằng cách tách biệt rõ ràng giữa Controller (nhận request/response), Service Layer (xử lý business logic) và Data Access Layer (tương tác database).
Ghi nhớ nhanh
- Nắm vững kiến thức cốt lõi về Event Loop, Libuv và cơ chế bất đồng bộ thay vì học vẹt.
- Tuyệt đối tránh các hàm synchronous trong production code để không làm block server.
- Luôn chủ động trong việc xử lý lỗi (error handling) và kiểm soát memory leak.
- Trình bày tư duy thiết kế hệ thống sạch, tuân thủ nguyên tắc phân tách các tầng logic (Layers).