fs.appendFile(): Đỉnh cao ghi nhật ký, không sợ mất dữ liệu cũ!
Nodejs

fs.appendFile(): Đỉnh cao ghi nhật ký, không sợ mất dữ liệu cũ!

Author

Admin System

@root

Ngày xuất bản

19 Mar, 2026

Lượt xem

4 Lượt

"fs.appendFile()"

Chào các "coder hệ Gen Z"! Anh Creyt lại lên sóng rồi đây. Hôm nay, chúng ta sẽ "vibe check" một khái niệm nghe thì có vẻ "nghiêm túc" nhưng lại cực kỳ "chill" và quan trọng trong Node.js: fs.appendFile(). Nghe tên là thấy có "vibe" ghi chép rồi đúng không? Cùng đào sâu nhé!

1. fs.appendFile() là gì mà "hot" thế?

Thử tưởng tượng thế này: Bạn đang "chat" với "crush" trên một ứng dụng nhắn tin nào đó. Mỗi khi bạn gửi một tin nhắn mới, nó sẽ tự động được thêm vào cuối cùng của cuộc hội thoại, đúng không? Nó không bao giờ xóa tin nhắn cũ để thay bằng tin nhắn mới. Đó chính là fs.appendFile() trong "thế giới" Node.js!

Nói một cách "coder-friendly" hơn, fs.appendFile() là một hàm trong module fs (File System) của Node.js, cho phép bạn thêm nội dung vào cuối một tệp tin hiện có. Nếu tệp tin đó chưa tồn tại, nó sẽ tự động tạo một tệp tin mới và ghi nội dung đó vào. "Ngầu" chưa?

Để làm gì ư? Đơn giản là để "ghi nhật ký" (logging), "ghi lại lịch sử" (history tracking), hay "ghi lại sự kiện" (event logging) mà không làm mất đi những gì đã có trước đó. Nó như cuốn sổ tay thần kỳ của bạn vậy, cứ viết thêm vào, không bao giờ phải xé trang cũ.

2. Code Ví Dụ Minh Họa: "Flex" ngay kỹ năng với fs.appendFile()

Anh em "dev" thích xem code hơn là đọc chữ đúng không? "Đét go"!

Đầu tiên, hãy tạo một file app.js và một file daily_log.txt (nếu chưa có, Node.js sẽ tự tạo).

const fs = require('fs');
const path = require('path');

const logFileName = 'daily_log.txt';
const logFilePath = path.join(__dirname, logFileName);

// Hàm để ghi log
function writeLog(message) {
  const timestamp = new Date().toISOString(); // Lấy thời gian hiện tại theo chuẩn ISO
  const logEntry = `[${timestamp}] ${message}\n`; // Thêm dấu xuống dòng để mỗi log là một dòng mới

  // Sử dụng fs.appendFile với callback
  fs.appendFile(logFilePath, logEntry, 'utf8', (err) => {
    if (err) {
      console.error('🚫 Ơ kìa, lỗi khi ghi log rồi:', err);
      return;
    }
    console.log(`✅ Đã ghi log thành công: "${message.trim()}"` + ` vào file ${logFileName}`);
  });
}

// Ví dụ sử dụng:
console.log('--- Bắt đầu ghi log ---');
writeLog('Người dùng Creyt vừa đăng nhập.');

setTimeout(() => {
  writeLog('Có một lỗi nhẹ xảy ra ở module thanh toán.');
}, 1000); // Ghi log sau 1 giây

setTimeout(() => {
  writeLog('Người dùng GenZ đã thanh toán đơn hàng #12345.');
}, 2000); // Ghi log sau 2 giây

// Bonus: Dùng Promise/async-await cho "clean code" hơn
const fsPromises = require('fs').promises;

async function writeLogAsync(message) {
  const timestamp = new Date().toISOString();
  const logEntry = `[${timestamp}] (Async) ${message}\n`;
  try {
    await fsPromises.appendFile(logFilePath, logEntry, 'utf8');
    console.log(`✅ Đã ghi log (Async) thành công: "${message.trim()}"` + ` vào file ${logFileName}`);
  } catch (err) {
    console.error('🚫 Lỗi khi ghi log (Async):', err);
  }
}

setTimeout(() => {
  writeLogAsync('Một sự kiện quan trọng đã xảy ra, cần ghi lại gấp!');
}, 3000);

console.log('--- Đã gửi các yêu cầu ghi log ---');

Khi bạn chạy node app.js, file daily_log.txt của bạn sẽ trông như thế này (thời gian sẽ khác):

[2023-10-27T08:00:00.123Z] Người dùng Creyt vừa đăng nhập.
[2023-10-27T08:00:01.456Z] Có một lỗi nhẹ xảy ra ở module thanh toán.
[2023-10-27T08:00:02.789Z] Người dùng GenZ đã thanh toán đơn hàng #12345.
[2023-10-27T08:00:03.999Z] (Async) Một sự kiện quan trọng đã xảy ra, cần ghi lại gấp!

Thấy chưa? Mỗi lần chạy, nội dung mới sẽ được thêm vào cuối mà không ảnh hưởng gì đến các dòng trước đó. "Nghe vibe" logging chưa?

Illustration

3. Mẹo (Best Practices) để ghi nhớ và dùng "chuẩn bài"

  • Asynchronous là "chân ái": fs.appendFile() là một hàm bất đồng bộ (asynchronous). Điều này có nghĩa là Node.js sẽ không chờ đợi việc ghi file hoàn tất rồi mới làm việc khác. Nó sẽ "quăng" việc ghi file cho hệ điều hành lo, rồi tự nó "lướt" sang các tác vụ khác. Điều này giúp ứng dụng của bạn không bị "đứng hình" (blocking) khi xử lý các tác vụ I/O chậm. Luôn dùng callback hoặc async/await để xử lý kết quả (thành công/thất bại) nhé!

    Gợi Ý Đọc Tiếp
    Node.js Core Modules: Vũ Khí Bí Mật Của Dev Gen Z

    2 Lượt xem

  • Xử lý lỗi là "must-have": Đừng bao giờ "quên" xử lý lỗi (error handling). Việc ghi file có thể thất bại vì nhiều lý do (không đủ quyền, ổ đĩa đầy, tên file không hợp lệ...). Luôn kiểm tra biến err trong callback hoặc dùng try...catch với async/await để ứng dụng của bạn không bị "crash" bất ngờ.

  • Mã hóa (Encoding) là "key": Mặc định, appendFile sử dụng 'utf8' (UTF-8). Đây là lựa chọn tốt nhất cho hầu hết các trường hợp, đặc biệt khi bạn làm việc với nội dung có tiếng Việt hoặc các ký tự đặc biệt. Hãy luôn chỉ định 'utf8' tường minh để đảm bảo tính nhất quán.

  • Đồng bộ (Synchronous) chỉ là "phụ": Node.js cũng có fs.appendFileSync() (có chữ Sync ở cuối). Hàm này hoạt động đồng bộ, nghĩa là nó sẽ chặn (block) toàn bộ luồng thực thi của ứng dụng cho đến khi việc ghi file hoàn tất. Tránh dùng nó trong môi trường server (production) vì nó có thể làm ứng dụng của bạn bị "treo" nếu việc ghi file mất thời gian. Chỉ dùng khi bạn biết chắc mình đang làm gì, ví dụ: các script nhỏ, khởi tạo ứng dụng...

4. Ứng dụng thực tế: "Nhìn đâu cũng thấy em"

fs.appendFile() (hoặc các biến thể của nó) được ứng dụng "cực nhiều" trong đời sống lập trình:

  • Hệ thống Log (Server Logs): Đây là "use case" kinh điển nhất. Các server web như Nginx, Apache, hay thậm chí là ứng dụng Node.js của bạn đều cần ghi lại nhật ký hoạt động: ai truy cập, truy cập lúc nào, có lỗi gì xảy ra không. fs.appendFile() là "ứng cử viên sáng giá" cho việc này.
  • Ghi lại sự kiện người dùng (User Activity Tracking): Một số ứng dụng có thể ghi lại hành vi người dùng (ví dụ: người dùng click vào nút nào, xem trang nào) vào các file log đơn giản để phân tích sau này.
  • Thu thập dữ liệu cảm biến (Sensor Data Collection): Trong các dự án IoT (Internet of Things) đơn giản, dữ liệu từ cảm biến có thể được ghi liên tục vào một file để lưu trữ tạm thời trước khi xử lý hoặc gửi lên database lớn hơn.
  • Chat Logs / Lịch sử tin nhắn: Như ví dụ "chat với crush" ban đầu, các hệ thống chat đơn giản có thể dùng cơ chế này để lưu trữ lịch sử tin nhắn.

5. Thử nghiệm đã từng và nên dùng cho "case" nào?

Anh Creyt đã từng "thử nghiệm" fs.appendFile() trong rất nhiều dự án, từ nhỏ đến lớn. Nó là một "công cụ" cực kỳ hữu ích khi bạn cần:

  • Ghi log liên tục: Khi bạn cần một dòng thời gian các sự kiện mà không cần truy vấn phức tạp hay cấu trúc dữ liệu cầu kỳ. Ví dụ: log lỗi, log truy cập, log hành động admin.
  • Lưu trữ dữ liệu dạng văn bản đơn giản: Nếu dữ liệu của bạn chỉ là các dòng text, không cần quan hệ hay schema phức tạp, và bạn chỉ muốn thêm vào cuối. Ví dụ: danh sách email đăng ký tạm thời, danh sách các URL đã crawl.
  • Tránh ghi đè dữ liệu cũ: Đây là điểm mạnh nhất của nó. Bạn không muốn "lỡ tay" xóa mất dữ liệu quan trọng!

Tuyệt đối KHÔNG nên dùng fs.appendFile() (hoặc bất kỳ phương pháp ghi file text nào) trong các trường hợp sau:

  • Lưu trữ dữ liệu phức tạp, có cấu trúc: Khi bạn cần lưu trữ đối tượng JSON, dữ liệu quan hệ, hoặc cần tìm kiếm, cập nhật, xóa dữ liệu một cách hiệu quả. Lúc này, hãy "flex" kiến thức về Database (MongoDB, PostgreSQL, MySQL...) hoặc các hệ thống lưu trữ chuyên biệt khác.
  • Hiệu năng cao, đọc/ghi ngẫu nhiên: Nếu ứng dụng của bạn cần đọc/ghi dữ liệu liên tục với tần suất cực cao hoặc cần truy cập vào một vị trí cụ thể trong file (không phải chỉ ở cuối), thì việc đọc/ghi file trực tiếp sẽ không hiệu quả bằng các giải pháp chuyên dụng.
  • Dữ liệu nhạy cảm, cần bảo mật cao: File text rất dễ bị đọc. Với dữ liệu nhạy cảm, hãy dùng database có mã hóa và hệ thống quản lý quyền chặt chẽ.

Nhớ nhé, fs.appendFile() là một "người bạn" tuyệt vời cho việc ghi log và thêm dữ liệu đơn giản. Hãy dùng nó một cách thông minh để ứng dụng của bạn luôn "smooth" và "ổn áp"!

Giờ thì "go code" và thử nghiệm ngay đi các "dev"! Anh Creyt tin các bạn sẽ "master" nó trong "một nốt nhạc"!

Thuộc Series: Nodejs

Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!