Chuyên mục

Nodejs

Nodejs tutolrial

147 bài viết
fs.statSync(): Thám Tử File Của Node.js - Nhanh Gọn Lẹ!
20/03/2026

fs.statSync(): Thám Tử File Của Node.js - Nhanh Gọn Lẹ!

Chào các dân chơi Node.js! Anh Creyt lại lên sóng đây. Hôm nay, chúng ta sẽ cùng "mổ xẻ" một "thám tử" siêu đẳng trong thế giới file system của Node.js: fs.statSync(). Nghe cái tên có vẻ "hàn lâm" nhưng thực ra nó là một công cụ cực kỳ hữu ích, đặc biệt khi bạn cần "xem mặt đặt tên" một file hay thư mục nào đó ngay lập tức. fs.statSync() là gì? Để làm gì? Đầu tiên, hãy tưởng tượng thế này: bạn đang lướt TikTok, thấy một video hay ho và muốn biết "hồ sơ" của nó – nặng bao nhiêu, đăng từ bao giờ, có phải là video hay ảnh không? Trong thế giới của Node.js, khi bạn cần "soi" một file hay thư mục, fs.statSync() chính là "công cụ xem thông tin" nhanh gọn lẹ của bạn. Nói một cách "chuẩn chỉnh" hơn, fs.statSync() là một phương thức đồng bộ (synchronous) thuộc module fs (File System) của Node.js. Nhiệm vụ của nó là đọc và trả về thông tin metadata chi tiết về một đường dẫn file hoặc thư mục cụ thể. "Metadata" ở đây chính là những thông tin như: Kích thước của file (size). Loại đối tượng đó là gì (file, thư mục, symbolic link, v.v.) qua các hàm isFile(), isDirectory(), isSymbolicLink(). Ngày tạo (birthtime). Ngày sửa đổi cuối cùng (mtime). Quyền truy cập (mode). Và nhiều thông tin khác nữa... Chữ Sync ở cuối tên hàm cực kỳ quan trọng, nó báo hiệu rằng hàm này sẽ chặn (block) luồng thực thi chính của chương trình cho đến khi nó hoàn thành việc đọc thông tin. Tức là, khi bạn gọi fs.statSync(), chương trình của bạn sẽ "đứng yên chờ đợi" cho đến khi có kết quả trả về, không làm bất cứ việc gì khác. Nghe có vẻ "nguy hiểm" nhưng đôi khi, đó lại là thứ bạn cần! Code Ví Dụ Minh Hoạ Rõ Ràng Để các bạn dễ hình dung, anh Creyt đã chuẩn bị một ví dụ "thực chiến" đây. Chúng ta sẽ tạo ra một file và một thư mục ảo, sau đó dùng fs.statSync() để "điều tra" chúng. const fs = require('fs'); const path = require('path'); // Bước 1: Chuẩn bị "hiện trường" - tạo file và folder giả định để test const filePath = path.join(__dirname, 'creyt_note.txt'); const dirPath = path.join(__dirname, 'creyt_project_folder'); const nonExistentPath = path.join(__dirname, 'file_khong_ton_tai.txt'); try { // Ghi một vài dòng vào file creyt_note.txt fs.writeFileSync(filePath, 'Hello các bạn gen Z! Đây là ghi chú của thầy Creyt.'); // Tạo thư mục creyt_project_folder fs.mkdirSync(dirPath, { recursive: true }); console.log('--- Đang "điều tra" file creyt_note.txt ---'); const fileStats = fs.statSync(filePath); // "Soi" file console.log(`Kích thước file: ${fileStats.size} bytes`); console.log(`Có phải là thư mục?: ${fileStats.isDirectory()}`); console.log(`Có phải là file?: ${fileStats.isFile()}`); console.log(`Ngày tạo file: ${fileStats.birthtime}`); console.log(`Ngày sửa đổi cuối cùng: ${fileStats.mtime}`); console.log(' --- Đang "điều tra" thư mục creyt_project_folder ---'); const dirStats = fs.statSync(dirPath); // "Soi" thư mục console.log(`Kích thước thư mục: ${dirStats.size} bytes (lưu ý: trên Linux/macOS, kích thước thư mục rỗng thường là 4096 bytes)`); console.log(`Có phải là thư mục?: ${dirStats.isDirectory()}`); console.log(`Có phải là file?: ${dirStats.isFile()}`); console.log(`Ngày tạo thư mục: ${dirStats.birthtime}`); console.log(`Ngày sửa đổi cuối cùng: ${dirStats.mtime}`); console.log(' --- Thử "điều tra" một file không tồn tại (sẽ lỗi) ---'); try { fs.statSync(nonExistentPath); } catch (error) { if (error.code === 'ENOENT') { // ENOENT: Error NO ENTry (file or directory does not exist) console.error(`Lỗi: "${nonExistentPath}" không tồn tại. Chuẩn bài!`); } else { console.error(`Lỗi khác xảy ra: ${error.message}`); } } } catch (err) { console.error('Có lỗi xảy ra trong quá trình chuẩn bị file/folder hoặc đọc stats:', err); } finally { // Bước 3: "Dọn dẹp hiện trường" - xóa file và folder đã tạo if (fs.existsSync(filePath)) fs.unlinkSync(filePath); if (fs.existsSync(dirPath)) fs.rmdirSync(dirPath, { recursive: true }); console.log('\nĐã dọn dẹp các file và folder tạm thời.'); } Khi chạy đoạn code trên, bạn sẽ thấy nó in ra tất tần tật thông tin về creyt_note.txt và creyt_project_folder, từ kích thước cho đến ngày sinh, ngày "tái tạo" cuối cùng. Và đặc biệt, nó sẽ bắt được lỗi khi bạn cố gắng "soi" một file không tồn tại. Mẹo (Best Practices) & Ghi nhớ từ anh Creyt "Sync" là đồng bộ, không phải "Synergy": Nhớ kỹ chữ Sync trong fs.statSync() nghĩa là nó sẽ block luồng chính. Giống như bạn đang "đứng chờ" kết quả ngay lập tức, không làm việc gì khác được cho đến khi có thông tin. Điều này cực kỳ quan trọng khi bạn code backend! Thận trọng với Sync trong ứng dụng lớn: Trong các ứng dụng server (như web API), việc block luồng chính là "tối kỵ". Nó sẽ làm tắc nghẽn các request khác, giống như một con đường đông đúc bị kẹt xe chỉ vì một chiếc xe đang chờ đổ xăng. Thay vào đó, hãy ưu tiên bản bất đồng bộ (asynchronous) là fs.stat() hoặc dùng fs.promises.stat với async/await để hệ thống hoạt động mượt mà hơn. Luôn dùng try...catch: fs.statSync() sẽ "quăng lỗi" (throw an error) nếu đường dẫn không tồn tại hoặc bạn không có quyền truy cập. Luôn "bọc" nó trong try...catch để ứng dụng của bạn không bị "sập nguồn" đột ngột. Các thuộc tính "vàng": isDirectory(), isFile(), size, birthtime, mtime là những "chứng minh thư" cơ bản và thường dùng nhất của mọi file/folder. Nắm chắc chúng là bạn đã có chìa khóa để "đọc vị" mọi thứ rồi. Ứng dụng thực tế: fs.statSync() "làm được gì"? fs.statSync() (hoặc phiên bản async của nó) là "người hùng thầm lặng" trong nhiều ứng dụng mà bạn dùng hàng ngày: Trình quản lý file (File Manager): Các ứng dụng như Windows Explorer, Finder trên macOS, hoặc các trình quản lý file trên web (như Admin Panel của WordPress) đều dùng thông tin này để hiển thị kích thước, ngày sửa đổi, biểu tượng file/thư mục. Kiểm tra file upload: Khi bạn upload ảnh lên Facebook, Instagram, hệ thống backend sẽ dùng stat để kiểm tra xem đó có thực sự là một file, kích thước có vượt quá giới hạn không trước khi lưu trữ. Hệ thống cache/build: Các công cụ build như Webpack, Gulp, hay các hệ thống cache thường kiểm tra mtime của file nguồn. Nếu mtime thay đổi, họ biết rằng file đã được sửa đổi và cần phải rebuild hoặc invalidate cache. Hệ thống backup: Các phần mềm backup chỉ sao lưu những file đã thay đổi kể từ lần backup cuối cùng, dựa vào mtime để tối ưu hiệu suất. Kiểm tra đường dẫn: Đảm bảo đường dẫn người dùng cung cấp là thư mục trước khi thực hiện các thao tác chỉ dành cho thư mục (ví dụ: rmdir chỉ xóa thư mục). Thử nghiệm đã từng và Hướng dẫn nên dùng cho case nào Anh Creyt đã từng "thử nghiệm" và "trải đời" với fs.statSync() rất nhiều. Đây là vài lời khuyên chân thành: Nên dùng fs.statSync() khi nào? Script CLI (Command Line Interface) đơn giản: Khi bạn viết các script chạy một lần, không yêu cầu phản hồi ngay lập tức cho nhiều người dùng (ví dụ: script dọn dẹp thư mục, script kiểm tra cấu hình trước khi deploy). Việc block luồng không phải là vấn đề lớn. Giai đoạn khởi tạo ứng dụng: Trong các hàm khởi tạo (initialization) của một ứng dụng, khi bạn cần kiểm tra sự tồn tại của file cấu hình ngay lập tức để quyết định cách ứng dụng sẽ chạy. Lúc này, block một chút cũng không sao vì ứng dụng chưa đi vào hoạt động chính thức. Trong các bài kiểm tra (Unit Tests): Để thiết lập môi trường test hoặc kiểm tra kết quả sau khi một hàm chạy xong. Tests thường chạy tuần tự, nên Sync là ổn. Không nên dùng fs.statSync() khi nào? Trong ứng dụng Web Server/API Server: Tuyệt đối tránh trong các hàm xử lý request của người dùng (route handlers). Dùng fs.stat (callback-based) hoặc fs.promises.stat (async/await) để đảm bảo server có thể xử lý nhiều request đồng thời mà không bị treo. Khi thao tác với số lượng lớn file: Nếu bạn cần xử lý hàng trăm, hàng ngàn file, mỗi lần gọi statSync sẽ gây ra độ trễ đáng kể và làm chậm toàn bộ quá trình. Nhớ nhé, fs.statSync() là một "thám tử" nhanh nhẹn nhưng đôi khi hơi "độc đoán" vì nó bắt bạn phải chờ. Hãy chọn đúng thời điểm để "triệu hồi" nó, và bạn sẽ thấy sức mạnh của nó trong việc quản lý file hệ thống! Chúc các bạn code vui vẻ và luôn "ngầu" như anh Creyt! 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é!

51 Đọc tiếp
fs.stat(): Thám tử file của Node.js - Gen Z cần biết!
20/03/2026

fs.stat(): Thám tử file của Node.js - Gen Z cần biết!

Chào các "coder nhí" năng động của Gen Z! Hôm nay, anh Creyt sẽ giới thiệu cho mấy đứa một công cụ cực kỳ hữu ích trong Node.js, giúp mấy đứa "thám hiểm" thế giới file và thư mục một cách chuyên nghiệp: đó chính là fs.stat(). Nghe có vẻ khô khan nhưng tin anh đi, nó "ngầu" hơn mấy đứa tưởng đấy! fs.stat() là gì mà "hot" thế? "Mấy đứa cứ hình dung thế này: mỗi file hay thư mục trên máy tính của chúng ta đều có một "căn cước công dân" riêng, chứa đầy đủ thông tin cá nhân như tên, ngày sinh, chiều cao, cân nặng... À nhầm, ý anh là tên, kích thước, ngày tạo, ngày sửa đổi, và quan trọng nhất là nó là "file" hay "folder"." fs.stat() chính là "cảnh sát điều tra" giúp chúng ta đọc được cái "căn cước" đó. Nói một cách "code-ese" hơn, fs.stat() trong module fs (File System) của Node.js dùng để lấy thông tin metadata của một file hoặc thư mục. Nó không đọc nội dung file đâu nhé, mà chỉ quan tâm đến các thuộc tính bên ngoài của nó thôi. Như kiểu mấy đứa check info crush trước khi inbox vậy đó: xem ảnh đại diện, status, ngày sinh, chứ đâu có đọc tin nhắn riêng tư của người ta đâu, đúng không? Để làm gì? Đơn giản là để "biết người biết ta". Trước khi mấy đứa định mở một file, xóa nó, hay copy nó đi đâu đó, mấy đứa cần biết: File đó có thực sự tồn tại không? Nó là một file hay một thư mục? Kích thước của nó bao nhiêu? Có vượt quá giới hạn cho phép không? Nó được tạo ra khi nào? Sửa đổi lần cuối lúc nào? Có thông tin này trong tay, mấy đứa sẽ tránh được hàng tá lỗi vặt và làm cho code của mình "cứng cáp" hơn nhiều. Code Ví Dụ: "Bóc phốt" file với fs.stat() Trong Node.js hiện đại, anh Creyt khuyên mấy đứa nên dùng phiên bản Promise-based của fs để code sạch sẽ và dễ đọc hơn, đặc biệt khi làm việc với các tác vụ bất đồng bộ. Đây là cách "bóc phốt" một file: const fs = require('fs').promises; // Import phiên bản Promise của fs const path = require('path'); async function getFileInfo(filePath) { try { const stats = await fs.stat(filePath); // Dùng await để chờ kết quả console.log(`--- Thông tin File/Thư mục: ${filePath} ---`); console.log(`Kích thước: ${stats.size} bytes`); console.log(`Là file? ${stats.isFile()}`); console.log(`Là thư mục? ${stats.isDirectory()}`); console.log(`Thời gian tạo: ${stats.birthtime.toLocaleString()}`); console.log(`Thời gian sửa đổi cuối: ${stats.mtime.toLocaleString()}`); console.log(`Thời gian truy cập cuối: ${stats.atime.toLocaleString()}`); console.log(`Thời gian thay đổi inode: ${stats.ctime.toLocaleString()}`); if (stats.isFile()) { console.log(`Đây là một file.`); } else if (stats.isDirectory()) { console.log(`Đây là một thư mục.`); } else { console.log(`Loại khác (ví dụ: symbolic link, pipe...).`); } return stats; } catch (error) { if (error.code === 'ENOENT') { console.error(`Lỗi: Không tìm thấy file hoặc thư mục tại đường dẫn: ${filePath}`); } else { console.error(`Lỗi khi lấy thông tin cho ${filePath}:`, error.message); } return null; } } // Tạo một file tạm để thử nghiệm (nếu chưa có) fs.writeFile('my_test_file.txt', 'Hello Gen Z, this is a test file!') .then(() => { console.log('Đã tạo file my_test_file.txt.'); return getFileInfo('my_test_file.txt'); }) .then(() => getFileInfo('.')) // Lấy thông tin của thư mục hiện tại .then(() => getFileInfo('non_existent_file.txt')) // Thử với file không tồn tại .catch(err => console.error('Lỗi chung:', err.message)); Giải thích sơ bộ cái stats object mà fs.stat() trả về: Nó giống như một "bộ hồ sơ" đầy đủ, mấy đứa có thể truy cập các thuộc tính sau: stats.isFile(): Trả về true nếu đó là một file thông thường. stats.isDirectory(): Trả về true nếu đó là một thư mục. stats.size: Kích thước của file/thư mục (tính bằng byte). stats.birthtime: Thời gian tạo file/thư mục (đối tượng Date). stats.mtime: Thời gian sửa đổi nội dung cuối cùng (modification time). stats.atime: Thời gian truy cập cuối cùng (access time). stats.ctime: Thời gian thay đổi trạng thái (change time, ví dụ: quyền truy cập, chủ sở hữu). Mẹo của "thám tử" Creyt (Best Practices) Luôn dùng Async: Mấy đứa nhớ nhé, Node.js sinh ra là để xử lý bất đồng bộ (non-blocking I/O). Vì vậy, hãy luôn luôn dùng fs.promises.stat() (với async/await) hoặc fs.stat() (với callback) thay vì fs.statSync(). Dùng Sync chỉ khi mấy đứa biết chắc chắn là mình đang ở trong một script CLI đơn giản và không muốn block cả ứng dụng của mình. "Đừng tin ai cả, hãy stat trước!": Giống như khi mấy đứa muốn tải ảnh lên mạng, mấy đứa phải kiểm tra xem nó có đúng định dạng không, kích thước có quá lớn không. Tương tự, trước khi xử lý bất kỳ file nào, hãy dùng fs.stat() để kiểm tra sự tồn tại, loại và các thuộc tính khác. Tránh được lỗi ENOENT (Error NO ENTry - không tìm thấy) hoặc các lỗi khác do xử lý sai loại file. Xử lý lỗi "thanh lịch": Luôn bao bọc lời gọi fs.stat() trong try...catch (với async/await) hoặc kiểm tra error trong callback. File không tồn tại là lỗi thường gặp nhất, và mấy đứa cần có kế hoạch xử lý nó. Ứng dụng thực tế của fs.stat() (không phải chỉ trên lý thuyết) "Mấy đứa nghĩ xem, cái gì mà "thám tử" fs.stat() có thể làm được trong thế giới thực?" Nhiều lắm chứ! Hệ thống quản lý file (File Explorer, Google Drive, Dropbox): Khi mấy đứa mở File Explorer trên Windows hay Finder trên macOS, nó liên tục dùng các chức năng tương tự fs.stat() để hiển thị tên file, kích thước, ngày sửa đổi của từng file/thư mục. Các dịch vụ lưu trữ đám mây cũng dựa vào đó để đồng bộ hóa, kiểm tra phiên bản file. Các công cụ Build (Webpack, Gulp, Vite): Khi mấy đứa code frontend, các công cụ này sẽ theo dõi sự thay đổi của file (mtime) để biết khi nào cần biên dịch lại code, tối ưu hóa hiệu suất build. Server tải file/upload file: Trước khi cho người dùng tải một file lên, server có thể dùng fs.stat() để kiểm tra kích thước file tạm thời, đảm bảo nó không vượt quá giới hạn cho phép, tránh làm sập server vì quá tải. Content Management Systems (CMS) như WordPress, Strapi: Khi mấy đứa upload ảnh, video, CMS sẽ kiểm tra kích thước, loại file, và thậm chí cả mtime để quản lý phiên bản của media đó. Thử nghiệm và Nên dùng cho Case nào? "Hồi xưa, anh Creyt cũng từng 'ngây thơ' dùng fs.statSync() trong một script nhỏ để duyệt qua hàng ngàn file và resize ảnh. Kết quả là script chạy chậm như rùa bò, block cả tiến trình vì nó phải chờ từng file một. Từ đó anh mới thấm thía rằng, với Node.js, cứ cái gì liên quan đến I/O (input/output) thì phải dùng bất đồng bộ mới là chân ái!" Vậy, nên dùng fs.stat() cho những trường hợp nào? Kiểm tra sự tồn tại: Đảm bảo một file hay thư mục có tồn tại trước khi thực hiện các thao tác khác lên nó. Phân loại: Xác định xem một đường dẫn cụ thể trỏ đến một file hay một thư mục. Rất hữu ích khi mấy đứa muốn duyệt qua các thư mục con hoặc xử lý riêng từng loại. Kiểm tra kích thước: Ví dụ, trước khi đọc toàn bộ nội dung của một file lớn vào bộ nhớ, mấy đứa có thể kiểm tra kích thước của nó để tránh tràn RAM. Kiểm tra thời gian: Dùng mtime để tạo logic caching, chỉ tải lại file nếu nó đã được sửa đổi. Hoặc dùng birthtime để sắp xếp file theo thời gian tạo. fs.stat() giống như một "người gác cổng" thông minh, giúp mấy đứa có được cái nhìn tổng quan về "khách" (file/thư mục) trước khi quyết định cho nó vào nhà (xử lý). Nắm vững nó, mấy đứa sẽ viết được những ứng dụng Node.js an toàn và hiệu quả hơn rất nhiều! 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é!

49 Đọc tiếp
fs.rmdirSync(): Dọn Nhà Chớp Nhoáng trong Node.js, Cẩn Thận Kẻo Toang!
20/03/2026

fs.rmdirSync(): Dọn Nhà Chớp Nhoáng trong Node.js, Cẩn Thận Kẻo Toang!

Chào các "thợ code" Gen Z, hôm nay anh Creyt sẽ "khui" một ông già gân trong làng Node.js mà nhiều khi chúng ta vẫn phải đụng độ: fs.rmdirSync(). Nghe cái tên đã thấy mùi "synchronous" rồi đúng không? Y chang như bạn gọi thằng em ra dọn phòng, nó phải dọn xong bạn mới được làm việc khác vậy đó! fs.rmdirSync() là gì? Để làm gì? (Genz Edition) Nói một cách dễ hiểu, fs.rmdirSync() là lệnh xóa một thư mục RỖNG tức thì trong Node.js. Nó giống như bạn vẫy tay ra hiệu "xóa cái phòng này đi!" và Node.js sẽ ngay lập tức thực hiện, không cần hỏi han, không cần chờ đợi. "Xóa phát ăn ngay", "không chờ đợi, không drama" chính là nó đấy các bạn. Để làm gì? Đôi khi, trong quá trình phát triển, bạn cần dọn dẹp thư mục tạm, thư mục cache, hoặc thư mục chứa các file đã xử lý xong. Ví dụ, sau khi bạn nén xong một đống ảnh, bạn muốn xóa cái thư mục ảnh gốc đi cho nhẹ máy chủ. Hoặc trong các script build, bạn muốn xóa thư mục dist cũ trước khi tạo cái mới. Lúc này, fs.rmdirSync() (hoặc phiên bản hiện đại hơn của nó) sẽ là "người hùng thầm lặng" của bạn. Code Ví Dụ Minh Họa Rõ Ràng Trước khi đi sâu, hãy nhớ fs.rmdirSync() chỉ xóa được thư mục rỗng. Nếu thư mục có chứa gì đó, nó sẽ "dỗi" và quăng lỗi vào mặt bạn ngay. Đầu tiên, chúng ta cần module fs (File System) của Node.js. const fs = require('fs'); const path = require('path'); // 1. Tạo một thư mục để thử nghiệm const dirToCreate = path.join(__dirname, 'thu_muc_can_xoa'); const nestedFile = path.join(dirToCreate, 'tap_tin_trong.txt'); try { if (!fs.existsSync(dirToCreate)) { fs.mkdirSync(dirToCreate); // Tạo thư mục console.log(`Đã tạo thư mục: ${dirToCreate}`); } // 2. Thử xóa một thư mục RỖNG console.log('\n--- Thử xóa thư mục RỖNG ---'); const emptyDir = path.join(__dirname, 'thu_muc_rong_de_xoa'); if (!fs.existsSync(emptyDir)) { fs.mkdirSync(emptyDir); console.log(`Đã tạo thư mục rỗng: ${emptyDir}`); } try { fs.rmdirSync(emptyDir); console.log(`Đã xóa thư mục rỗng thành công: ${emptyDir}`); } catch (error) { console.error(`Lỗi khi xóa thư mục rỗng: ${error.message}`); } // 3. Thử xóa một thư mục CÓ CHỨA FILE (sẽ lỗi với rmdirSync) console.log('\n--- Thử xóa thư mục CÓ CHỨA FILE (sẽ lỗi với rmdirSync) ---'); fs.writeFileSync(nestedFile, 'Nội dung file này sẽ ngăn thư mục bị xóa bằng rmdirSync.'); console.log(`Đã tạo file trong thư mục: ${nestedFile}`); try { fs.rmdirSync(dirToCreate); console.log(`Đã xóa thư mục có file thành công: ${dirToCreate}`); // Sẽ không bao giờ chạy } catch (error) { console.error(`Lỗi khi xóa thư mục có file: ${error.message}`); // Đây là cái bạn sẽ thấy } // 4. Giới thiệu giải pháp hiện đại: fs.rmSync() // Lưu ý: fs.rmdirSync() đã bị DEPRECATED từ Node.js v14.14.0 // và v16.0.0. Thay vào đó, hãy dùng fs.rmSync() với tùy chọn recursive. console.log('\n--- Sử dụng fs.rmSync() hiện đại để xóa thư mục có file ---'); try { // Xóa file trước để thư mục rỗng, hoặc dùng recursive: true fs.unlinkSync(nestedFile); // Xóa file bên trong trước console.log(`Đã xóa file: ${nestedFile}`); // Hoặc cách hiện đại hơn, xóa cả thư mục lẫn file bên trong: // fs.rmSync(dirToCreate, { recursive: true, force: true }); // console.log(`Đã xóa thư mục (bao gồm cả file) bằng fs.rmSync(): ${dirToCreate}`); fs.rmSync(dirToCreate); // Thư mục đã rỗng sau khi unlink console.log(`Đã xóa thư mục rỗng bằng fs.rmSync(): ${dirToCreate}`); } catch (error) { console.error(`Lỗi khi xóa thư mục bằng fs.rmSync(): ${error.message}`); } } catch (error) { console.error(`Lỗi chung trong quá trình thử nghiệm: ${error.message}`); } // Dọn dẹp sau khi chạy ví dụ (đảm bảo không còn thư mục nào) process.on('exit', () => { const createdDirs = [dirToCreate, path.join(__dirname, 'thu_muc_rong_de_xoa')]; createdDirs.forEach(dir => { if (fs.existsSync(dir)) { try { // Đảm bảo thư mục rỗng trước khi xóa bằng rmdirSync // Hoặc dùng fs.rmSync để xóa mạnh tay hơn fs.rmSync(dir, { recursive: true, force: true }); console.log(`Đã dọn dẹp thư mục: ${dir}`); } catch (cleanupError) { console.error(`Lỗi khi dọn dẹp thư mục ${dir}: ${cleanupError.message}`); } } }); }); Mẹo hay và Best Practices từ anh Creyt (Thực tế và Dễ Nhớ) "Xóa nhầm là toang!" (Luôn kiểm tra đường dẫn): Trước khi xóa bất cứ thứ gì, hãy luôn luôn kiểm tra lại đường dẫn. Một đường dẫn sai có thể xóa nhầm cả thư mục gốc của dự án hoặc tệ hơn là của hệ thống. Dùng path.join để tạo đường dẫn an toàn. rmdirSync chỉ cho "nhà rỗng": Hãy coi fs.rmdirSync() như một người dọn dẹp chỉ chấp nhận phòng trống. Nếu có đồ đạc (file, thư mục con) bên trong, anh ta sẽ từ chối và báo lỗi. Để xóa cả "đồ đạc", bạn cần người dọn dẹp "mạnh tay" hơn (sẽ nói ở mẹo 4). "Đồng bộ" là "chờ đợi": Chữ Sync trong rmdirSync nghĩa là "đồng bộ". Tức là, mọi hoạt động khác của chương trình sẽ phải chờ cho đến khi thư mục được xóa xong. Trong các ứng dụng web hiệu năng cao, điều này có thể làm tắc nghẽn server. Nên ưu tiên các hàm bất đồng bộ (fs.promises.rmdir() hoặc fs.promises.rm()) nếu bạn không muốn server của mình "đứng hình" khi đang dọn dẹp. "Thế hệ mới" lên ngôi: fs.rmSync(): Này các Gen Z, fs.rmdirSync() đã chính thức bị DEPRECATED (nghĩa là Node.js không khuyến khích dùng nữa và có thể sẽ bị loại bỏ trong tương lai) từ Node.js v14.14.0 và v16.0.0. "Thế hệ mới" mà bạn nên dùng là fs.rmSync() (hoặc fs.rm nếu muốn bất đồng bộ). fs.rmSync(path, { recursive: true, force: true }): Đây mới là "lệnh đập cả nhà không cần biết có gì bên trong". Tùy chọn recursive: true cho phép xóa thư mục và tất cả nội dung bên trong nó (file, thư mục con), còn force: true sẽ bỏ qua lỗi nếu đường dẫn không tồn tại. Tuyệt vời cho việc dọn dẹp "tổng thể"! Luôn try...catch: Các thao tác với hệ thống file luôn tiềm ẩn rủi ro (không có quyền, thư mục không tồn tại, thư mục đang bị khóa...). Hãy luôn bọc chúng trong try...catch để chương trình không bị crash và bạn có thể xử lý lỗi một cách duyên dáng. Ứng Dụng Thực Tế (Websites/Apps) Trong thế giới thực, các thao tác xóa thư mục thường được dùng ở backend hoặc trong các công cụ phát triển: Build Tools (Webpack, Gulp, Vite): Trước khi một dự án web được build, các công cụ này thường xóa thư mục dist hoặc build cũ (chứa các file đã biên dịch, nén...) để đảm bảo một bản build sạch sẽ và mới tinh. fs.rmSync(path.join(__dirname, 'dist'), { recursive: true, force: true }); là một đoạn code quen thuộc. Cache Management: Các server lưu trữ tạm thời các file cache để tăng tốc độ phản hồi. Khi cache trở nên cũ hoặc quá lớn, một cron job (tác vụ định kỳ) có thể chạy để xóa các thư mục cache cũ bằng fs.rmSync. Temporary File Cleanup: Khi người dùng upload ảnh hoặc video lên website, các file này thường được lưu vào một thư mục tạm thời. Sau khi xử lý (ví dụ, resize, chuyển đổi định dạng), các file và thư mục tạm này cần được xóa đi để giải phóng dung lượng. Backend Services: Khi một tài khoản người dùng hoặc một dự án bị xóa khỏi hệ thống, các thư mục và file liên quan đến tài khoản/dự án đó trên server cần được dọn dẹp để đảm bảo dữ liệu nhạy cảm không còn và giải phóng tài nguyên. Thử Nghiệm Đã Từng và Nên Dùng Cho Case Nào Anh Creyt đã từng "ngây thơ" dùng fs.rmdirSync() trong một script dọn dẹp ảnh upload. Kết quả là, nếu một thư mục ảnh chưa được xử lý hết mà lại có file con bên trong, script crash ngay lập tức! Bài học xương máu: Đọc kỹ tài liệu và hiểu rõ giới hạn của từng hàm. Nên dùng fs.rmdirSync() (hoặc tốt hơn là fs.rmSync() với recursive: false) cho các trường hợp: Bạn chắc chắn 100% thư mục đó rỗng. Ví dụ, bạn vừa tạo nó, hoặc bạn vừa xóa hết nội dung bên trong bằng tay (hoặc bằng code). Trong các script nhỏ, chạy một lần (one-off scripts), hoặc các tác vụ setup/teardown trong unit tests, nơi việc chặn luồng chính không gây ra vấn đề hiệu năng. Khi bạn muốn kiểm soát chặt chẽ việc chỉ xóa thư mục rỗng để tránh nhầm lẫn. Lời khuyên của anh Creyt (Cho Gen Z hiện đại): Trong hầu hết các trường hợp cần xóa thư mục (dù rỗng hay không), hãy ưu tiên sử dụng fs.rmSync(path, { recursive: true, force: true }) (nếu cần đồng bộ) hoặc fs.promises.rm(path, { recursive: true, force: true }) (nếu muốn bất đồng bộ và không chặn luồng chính). Chúng mạnh mẽ hơn, linh hoạt hơn và là tiêu chuẩn hiện đại của Node.js. Hãy coi fs.rmdirSync() như một kỷ vật của quá khứ, biết để hiểu nhưng không nhất thiết phải dùng thường xuyên nữa nhé! 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é!

46 Đọc tiếp
Dọn Dẹp Folder Rỗng: fs.rmdir() & fs.rm() trong Node.js
20/03/2026

Dọn Dẹp Folder Rỗng: fs.rmdir() & fs.rm() trong Node.js

Chào các 'dev-er' trẻ tuổi, hôm nay chúng ta sẽ 'đào sâu' vào một khái niệm tưởng chừng đơn giản nhưng lại cực kỳ quan trọng trong thế giới Node.js: 'dọn dẹp nhà cửa' cho các thư mục của bạn. Cụ thể là 'thằng' fs.rmdir() và 'đứa em bá đạo' fs.rm(). 1. fs.rmdir() là gì? Nó để làm gì? Imagine thế này: Bạn vừa 'code xong' một project nhỏ, hoặc chạy một cái script nào đó tạo ra cả đống thư mục tạm bợ, xong xuôi rồi thì chúng rỗng toẹt ra đó, nhìn 'ngứa mắt' cực. fs.rmdir() sinh ra là để giải quyết cái sự 'ngứa mắt' đó! fs.rmdir() (File System Remove Directory) đúng như tên gọi, là một hàm trong module fs của Node.js giúp bạn xóa một thư mục. Nghe đơn giản đúng không? Nhưng mà, có một 'cú lừa' nho nhỏ ở đây, mà anh Creyt sẽ bật mí ngay. Nó giống như việc bạn muốn 'phá dỡ' một cái nhà kho cũ. fs.rmdir() chỉ cho phép bạn phá dỡ cái kho đó khi nó hoàn toàn trống rỗng, không còn một cái vớ, một cọng rơm hay bất cứ thứ gì bên trong. Nếu có dù chỉ là một hạt bụi, nó cũng 'báo lỗi' ngay tắp lự. Mục đích chính: Dọn dẹp các thư mục không còn cần thiết, giúp giữ cho cấu trúc dự án của bạn sạch sẽ, gọn gàng, tránh 'rác' digital. 2. Code Ví Dụ Minh Họa (Cả fs.rmdir và fs.rm) Ok, lý thuyết là vậy, giờ 'nhúng tay' vào code để thấy rõ hơn nhé. Anh sẽ cho ví dụ cả fs.rmdir (dù nó đang dần bị thay thế) và fs.rm (phiên bản hiện đại, 'xịn xò' hơn). Đầu tiên, hãy tạo một vài thư mục 'rác' để chúng ta thực hành: const fs = require('fs'); const path = require('path'); const emptyDir = path.join(__dirname, 'empty_folder'); const nonEmptyDir = path.join(__dirname, 'non_empty_folder'); const fileInNonEmpty = path.join(nonEmptyDir, 'my_file.txt'); // Tạo các thư mục và file để test fs.mkdirSync(emptyDir, { recursive: true }); fs.mkdirSync(nonEmptyDir, { recursive: true }); fs.writeFileSync(fileInNonEmpty, 'Nội dung file này sẽ ngăn xóa folder!', 'utf8'); console.log('Đã tạo các thư mục để thử nghiệm.'); console.log(`- Thư mục rỗng: ${emptyDir}`); console.log(`- Thư mục không rỗng: ${nonEmptyDir}`); Ví dụ 1: Sử dụng fs.rmdir() (Asynchronous) Đây là cách truyền thống, nhưng nhớ là nó chỉ hoạt động với thư mục rỗng! // Xóa thư mục rỗng bằng fs.rmdir() fs.rmdir(emptyDir, (err) => { if (err) { console.error(`Lỗi khi xóa ${emptyDir} bằng fs.rmdir():`, err.message); return; } console.log(`Đã xóa thành công thư mục rỗng: ${emptyDir} bằng fs.rmdir().`); // Thử xóa thư mục không rỗng bằng fs.rmdir() fs.rmdir(nonEmptyDir, (err) => { if (err) { console.error(`\nLỗi (có chủ đích) khi xóa ${nonEmptyDir} bằng fs.rmdir():`, err.message); console.log('--> Như anh Creyt đã nói, fs.rmdir() không thể xóa thư mục không rỗng!'); return; } console.log(`Đã xóa thành công thư mục không rỗng: ${nonEmptyDir} bằng fs.rmdir(). (KHÔNG THỂ XẢY RA)`); }); }); Khi chạy đoạn code trên, bạn sẽ thấy empty_folder bị xóa, nhưng non_empty_folder thì không, và một lỗi sẽ được log ra. Đó là 'cái bẫy' của fs.rmdir(). Ví dụ 2: Sử dụng fs.rm() (Phiên bản 'Pro' hơn) fs.rm() là 'thế hệ mới' được giới thiệu từ Node.js 14, nó 'đa năng' hơn rất nhiều. Nó có thể xóa cả file lẫn thư mục, và quan trọng nhất, nó có thể xóa thư mục không rỗng một cách 'thần thánh' với option recursive: true. // Hãy tạo lại emptyDir và nonEmptyDir để thử nghiệm với fs.rm() fs.mkdirSync(emptyDir, { recursive: true }); fs.mkdirSync(nonEmptyDir, { recursive: true }); fs.writeFileSync(fileInNonEmpty, 'Nội dung file này sẽ ngăn xóa folder!', 'utf8'); // Xóa thư mục rỗng bằng fs.rm() fs.rm(emptyDir, { recursive: true }, (err) => { if (err) { console.error(`Lỗi khi xóa ${emptyDir} bằng fs.rm():`, err.message); return; } console.log(`\nĐã xóa thành công thư mục rỗng: ${emptyDir} bằng fs.rm().`); // Xóa thư mục không rỗng bằng fs.rm() với recursive: true fs.rm(nonEmptyDir, { recursive: true, force: true }, (err) => { if (err) { console.error(`Lỗi khi xóa ${nonEmptyDir} bằng fs.rm():`, err.message); return; } console.log(`Đã xóa thành công thư mục không rỗng: ${nonEmptyDir} bằng fs.rm() với recursive: true.`); }); }); Giải thích recursive: true và force: true: recursive: true: Nói cho Node.js biết là 'hãy xóa tất cả mọi thứ bên trong thư mục này, rồi mới xóa chính nó'. Đây là 'chìa khóa' để xóa thư mục không rỗng. force: true: (Từ Node.js 15.0.0) Khi recursive là true, nếu một thư mục hoặc file không tồn tại, nó sẽ không báo lỗi. Điều này cực kỳ tiện lợi khi bạn không chắc chắn liệu thư mục có tồn tại hay không và chỉ muốn đảm bảo nó bị xóa. 3. Mẹo & Best Practices từ 'lão làng' Creyt Quên fs.rmdir() đi, dùng fs.rm()! Nghe có vẻ 'phũ' nhưng đây là lời khuyên chân thành nhất của anh. fs.rmdir() đã bị deprecated (không khuyến khích dùng nữa) từ Node.js 14. Dùng fs.rm() với recursive: true là tiêu chuẩn mới, 'xịn xò' hơn, ít rắc rối hơn nhiều. Luôn luôn xử lý lỗi: Dù bạn dùng fs.rmdir() hay fs.rm(), việc xóa file hệ thống luôn tiềm ẩn rủi ro. Hãy luôn có if (err) hoặc dùng try...catch nếu bạn dùng phiên bản Sync hoặc Promises để bắt lỗi và xử lý chúng một cách 'tử tế'. Chuyện 'xóa nhầm' là ác mộng của mọi developer. Cẩn trọng với recursive: true và force: true: Hai 'thần chú' này mạnh mẽ như 'thần chú Avada Kedavra' vậy. Nó có thể 'thổi bay' cả một cây thư mục mà không hỏi lại. Hãy chắc chắn bạn đang xóa đúng cái cần xóa! Double-check path trước khi chạy, đặc biệt trong môi trường production. Sử dụng path.join(): Luôn dùng path.join() để nối các phần của đường dẫn. Nó giúp code của bạn hoạt động mượt mà trên mọi hệ điều hành (Windows dùng \, Linux/macOS dùng /). 4. Ứng dụng Thực Tế (Ở đâu mà 'thằng' này được dùng?) Bạn nghĩ rằng việc xóa thư mục chỉ là 'chuyện vặt'? Sai lầm! Nó là một phần không thể thiếu trong nhiều hệ thống 'khủng' đấy: Dọn dẹp cache/file tạm: Các website lớn như Facebook, Google hay bất kỳ ứng dụng web nào có chức năng upload file đều có thể tạo ra các thư mục tạm thời để lưu trữ file trước khi xử lý. Sau khi xử lý xong, những thư mục này cần được dọn dẹp định kỳ. CI/CD Pipelines (Jenkins, GitHub Actions, GitLab CI): Khi bạn deploy code mới, các hệ thống tự động này thường tạo ra các thư mục build tạm thời. Sau khi build xong và deploy thành công, chúng sẽ xóa các thư mục đó để giải phóng không gian. Hệ thống quản lý nội dung (CMS): Nếu bạn có một CMS cho phép người dùng upload ảnh, video, và sau đó xóa chúng, thì backend sẽ cần dùng các hàm như fs.rm() để xóa file và thư mục tương ứng trên server. Local Development Tools: Các công cụ như npm khi chạy npm clean hay npm prune cũng ngầm dùng các chức năng tương tự để dọn dẹp các module không dùng nữa. 5. Thử Nghiệm của Anh Creyt và Hướng Dẫn Nên Dùng Cho Case Nào Anh Creyt đã từng 'đau đầu' với fs.rmdir() hồi mới vào nghề. Hồi đó, cứ muốn xóa một thư mục có file bên trong là y như rằng nó 'giãy nảy' lên báo lỗi ENOTEMPTY. Phải viết thêm một hàm đệ quy để duyệt qua từng file, xóa từng file, rồi mới xóa được thư mục mẹ. 'Cực hình' lắm! Bài học kinh nghiệm: Nếu bạn dùng Node.js 14 trở lên: Hãy 'mạnh dạn' dùng fs.rm(). Nó là 'cứu cánh' cho mọi vấn đề xóa thư mục. Đây là lựa chọn 'đi thẳng vào vấn đề' nhất. Dùng khi: Bạn cần xóa một thư mục bất kể nó rỗng hay không rỗng, ví dụ: xóa thư mục uploads/temp sau khi xử lý file, xóa thư mục build cũ, xóa toàn bộ thư mục node_modules để cài lại. Ví dụ: fs.rm('./my_project/temp_data', { recursive: true, force: true }, callback); Nếu bạn 'buộc phải' dùng Node.js cũ hơn (trước 14) hoặc muốn một lớp bảo vệ 'thừa thãi': Thì mới nghĩ đến fs.rmdir(). Nhưng hãy nhớ là bạn sẽ phải tự code logic để đảm bảo thư mục đó rỗng trước khi gọi rmdir. Dùng khi: Bạn có một logic phức tạp để đảm bảo thư mục đã 'sạch sẽ' trước khi xóa, hoặc trong các hệ thống legacy không thể nâng cấp Node.js. (Thực ra, nếu phải làm vậy thì cũng nên cân nhắc viết một hàm xóa đệ quy riêng). Ví dụ (Legacy): Bạn sẽ phải fs.readdir để list các file, fs.unlink từng file, rồi mới fs.rmdir. Lời khuyên cuối cùng từ anh Creyt: Trong thế giới lập trình hiện đại, hiệu quả và an toàn là trên hết. fs.rm() với recursive: true và force: true là 'công cụ' bạn cần thành thạo để 'dọn dẹp' file system của mình một cách 'chuyên nghiệp' và 'không đổ mồ hôi'. Hãy dùng nó một cách 'thông minh' và 'có trách nhiệm' nhé các 'dev-er'! 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é!

45 Đọc tiếp
fs.mkdirSync(): Phép thuật tạo folder 'tức thì' trong Node.js
20/03/2026

fs.mkdirSync(): Phép thuật tạo folder 'tức thì' trong Node.js

Chào các "thánh code" Gen Z! Hôm nay, anh Creyt sẽ "khui" một "bí kíp" mà tưởng chừng đơn giản nhưng lại cực kỳ quyền năng trong thế giới Node.js: fs.mkdirSync(). Nghe cái tên đã thấy "ngầu" rồi đúng không? Đừng lo, anh sẽ "mổ xẻ" nó một cách dễ hiểu nhất, đảm bảo "ngấm" ngay! 1. fs.mkdirSync(): "Thợ xây" thư mục siêu tốc của Node.js là gì? "Ngày xửa ngày xưa", khi các bạn muốn lưu trữ ảnh, video, hay bất kỳ "tài sản số" nào đó trên máy tính, các bạn thường tạo một cái thư mục (folder) bằng cách click chuột phải, chọn "New Folder" đúng không? Trong lập trình, đặc biệt là với Node.js, chúng ta cũng cần một "người" làm công việc đó một cách tự động, theo "kịch bản" của mình. Và đó chính là lúc fs.mkdirSync() "xuất hiện"! Hiểu đơn giản, fs.mkdirSync() là một "công cụ" trong module fs (File System) của Node.js, cho phép bạn tạo một thư mục mới ngay lập tức, tại một đường dẫn cụ thể. Cái chữ Sync ở cuối tên nó có nghĩa là "đồng bộ" (synchronous). Tức là, khi bạn gọi hàm này, toàn bộ chương trình của bạn sẽ "đứng hình" một chút để chờ cho đến khi thư mục được tạo xong xuôi, rồi mới tiếp tục chạy các dòng code tiếp theo. Giống như bạn đang xây nhà vậy, phải "đổ móng" xong xuôi thì mới tính đến chuyện "xây tường", "lợp mái" được, đúng không? 2. Sức mạnh của fs.mkdirSync(): Để làm gì trong thế giới code? Khi nào thì chúng ta cần đến "thợ xây" này? Nhiều lắm chứ! Tổ chức "gia tài số": Tưởng tượng bạn đang xây dựng một ứng dụng cho phép người dùng upload ảnh. Mỗi khi có ảnh mới, bạn muốn lưu nó vào một thư mục riêng biệt, ví dụ /uploads/user_id_123/ hoặc /uploads/2023-10-27/. fs.mkdirSync() chính là "trợ thủ" đắc lực giúp bạn tạo ra các thư mục này một cách tự động. Dọn dẹp "nhà cửa": Khi ứng dụng khởi động, bạn muốn chắc chắn rằng các thư mục quan trọng như logs (để ghi lại nhật ký), cache (để lưu dữ liệu tạm), hoặc temp (để chứa file tạm thời) đã tồn tại. Nếu chưa, fs.mkdirSync() sẽ "ra tay" tạo chúng ngay. "Đóng gói" dự án: Trong các dự án lớn, bạn có thể cần tạo ra một cấu trúc thư mục phức tạp cho các module, component, hay môi trường khác nhau. fs.mkdirSync() có thể giúp bạn tự động hóa quy trình này. 3. "Phép thuật" Code Ví Dụ: Dùng fs.mkdirSync() thế nào cho chuẩn bài? Để dùng fs.mkdirSync(), bạn cần "triệu hồi" module fs trước. Cú pháp cơ bản của nó là fs.mkdirSync(path, [options]). const fs = require('fs'); const path = require('path'); // Module 'path' giúp xử lý đường dẫn dễ dàng hơn // 1. Tạo thư mục đơn giản: Ví dụ 'uploads' để chứa file tải lên console.log('--- Ví dụ 1: Tạo thư mục đơn giản ---'); try { const dirName = 'uploads'; if (!fs.existsSync(dirName)) { // Luôn kiểm tra xem thư mục đã tồn tại chưa fs.mkdirSync(dirName); console.log(`Thư mục '${dirName}' đã được tạo thành công!`); } else { console.log(`Thư mục '${dirName}' đã tồn tại. Không cần tạo lại.`); } } catch (err) { console.error("Lỗi khi tạo thư mục đơn giản:", err.message); // Bắt lỗi và in ra } // 2. Tạo thư mục lồng nhau (nested directories): Ví dụ 'data/images/thumbnails' console.log('\n--- Ví dụ 2: Tạo thư mục lồng nhau ---'); try { const nestedDirPath = path.join('data', 'images', 'thumbnails'); // Với option { recursive: true }, Node.js sẽ tự động tạo các thư mục 'cha' nếu chúng chưa tồn tại if (!fs.existsSync(nestedDirPath)) { fs.mkdirSync(nestedDirPath, { recursive: true }); console.log(`Thư mục lồng nhau '${nestedDirPath}' đã được tạo thành công!`); } else { console.log(`Thư mục lồng nhau '${nestedDirPath}' đã tồn tại.`); } } catch (err) { console.error("Lỗi khi tạo thư mục lồng nhau:", err.message); } // 3. Tạo thư mục với quyền truy cập (permissions): Ví dụ 'private_data' chỉ chủ sở hữu được đọc/ghi/thực thi console.log('\n--- Ví dụ 3: Tạo thư mục với quyền truy cập ---'); try { const securedDir = 'private_data'; if (!fs.existsSync(securedDir)) { // mode: 0o700 nghĩa là: chỉ chủ sở hữu có quyền đọc (4), ghi (2), thực thi (1) => 4+2+1 = 7 // Các nhóm khác và người dùng khác không có quyền gì (0) fs.mkdirSync(securedDir, { mode: 0o700 }); console.log(`Thư mục '${securedDir}' với quyền 0o700 đã được tạo.`); } else { console.log(`Thư mục '${securedDir}' đã tồn tại.`); } } catch (err) { console.error("Lỗi khi tạo thư mục với quyền:", err.message); } // Cleanup (Xóa các thư mục đã tạo để chạy lại ví dụ) // console.log('\n--- Cleanup: Xóa thư mục ---'); // try { // fs.rmSync('uploads', { recursive: true, force: true }); // fs.rmSync('data', { recursive: true, force: true }); // fs.rmSync('private_data', { recursive: true, force: true }); // console.log('Đã xóa các thư mục thử nghiệm.'); // } catch (err) { // console.error("Lỗi khi xóa thư mục:", err.message); // } 4. Mẹo "nhà nghề" từ Creyt: Dùng sao cho "pro"? Muốn "lên trình" với fs.mkdirSync(), các bạn nhớ "bỏ túi" mấy cái mẹo này nhé: "Check hàng" trước khi "xuất chiêu": Luôn dùng fs.existsSync(path) để kiểm tra xem thư mục đã tồn tại chưa trước khi gọi fs.mkdirSync(). Điều này giúp bạn tránh được lỗi không đáng có và làm cho code "thân thiện" hơn. "Đánh nhanh thắng nhanh" với recursive: true: Khi bạn cần tạo một "chuỗi" thư mục lồng nhau (ví dụ: a/b/c/d), hãy dùng fs.mkdirSync(path, { recursive: true }). Node.js sẽ tự động tạo tất cả các thư mục "cha" nếu chúng chưa tồn tại. Tuyệt vời hơn là nếu thư mục cuối cùng đã tồn tại, nó sẽ không báo lỗi mà chỉ đơn giản là không làm gì cả. "Nhàn" hơn bao nhiêu là tự tay tạo từng cái, đúng không? "Đề phòng bất trắc" với try...catch: Dù đã kiểm tra trước, nhưng trong thế giới code, "chuyện gì cũng có thể xảy ra". Hãy luôn bọc fs.mkdirSync() trong khối try...catch để "bắt" và xử lý những lỗi không mong muốn (ví dụ: không có quyền tạo thư mục, đường dẫn không hợp lệ, v.v.). Hiểu rõ "tính cách" Sync: Nhớ rằng Sync có nghĩa là chặn luồng. Điều này ổn trong các script chạy một lần, hoặc khi khởi động ứng dụng. Nhưng tuyệt đối không nên dùng nó trong các tác vụ "nóng", liên tục của một server web (như xử lý request API), vì nó sẽ làm server của bạn "đứng hình" và "delay" tất cả các request khác. Trong những trường hợp đó, hãy dùng "anh em" của nó là fs.mkdir() (dạng callback) hoặc fs.promises.mkdir() (dạng Promise) để xử lý bất đồng bộ. "Bảo mật thông tin" với mode: Nếu thư mục bạn tạo chứa dữ liệu nhạy cảm, đừng quên đặt quyền truy cập (permissions) bằng option mode (ví dụ: 0o700 chỉ cho chủ sở hữu đọc/ghi/thực thi). Đây là một "thói quen tốt" của một dev "có tâm". 5. Ứng dụng thực tế: Ai đang "xài" fs.mkdirSync()? Các bạn có thể thấy fs.mkdirSync() (hoặc phiên bản async của nó) ở khắp mọi nơi trong các ứng dụng Node.js "đời thực": Hệ thống quản lý file: Các ứng dụng như Dropbox, Google Drive, hoặc bất kỳ website nào cho phép người dùng upload file đều cần tạo thư mục để lưu trữ dữ liệu. Ví dụ, mỗi khi một người dùng mới đăng ký, server có thể tự động tạo một thư mục riêng cho họ để lưu trữ tài liệu. Framework và CMS: Các framework như Next.js, Nuxt.js, hoặc các CMS (Content Management System) như Strapi, Ghost thường tạo các thư mục cache, logs, uploads khi ứng dụng được khởi tạo hoặc deploy lần đầu. Ứng dụng ghi log: Các hệ thống ghi nhật ký (logging systems) sẽ cần tạo thư mục để lưu trữ các file log theo ngày, theo loại, hoặc theo module. CI/CD Pipelines: Trong các quy trình tích hợp liên tục/triển khai liên tục (CI/CD), các script có thể tạo ra các thư mục tạm thời để lưu trữ các artifact (sản phẩm xây dựng) hoặc kết quả test. 6. Thử nghiệm và hướng dẫn: Khi nào nên "xuất chiêu"? Với fs.mkdirSync(), chúng ta có một "vũ khí" mạnh mẽ nhưng cần dùng đúng lúc, đúng chỗ. Nên dùng cho các "case" này: Khởi động ứng dụng: Khi ứng dụng Node.js của bạn vừa "thức giấc", việc kiểm tra và tạo các thư mục cần thiết cho logs, uploads, cache... là một tác vụ "một lần" và không ảnh hưởng nhiều đến hiệu suất. Đây là lúc fs.mkdirSync() "tỏa sáng" vì sự đơn giản và dễ đọc của nó. Các script tiện ích (CLI tools, utility scripts): Những script chạy từ dòng lệnh, thực hiện các tác vụ quản trị, sao lưu, hoặc tạo cấu trúc dự án. Trong những trường hợp này, việc chặn luồng không phải là vấn đề lớn. Trong quá trình cài đặt (installation scripts): Khi bạn cài đặt một package Node.js hoặc một ứng dụng, script cài đặt có thể dùng fs.mkdirSync() để tạo các thư mục cấu hình mặc định. Không nên dùng (hoặc cân nhắc kỹ) cho các "case" này: Trong các hàm xử lý request của server web (ví dụ: Express routes): Đây là "điều cấm kỵ" mà anh Creyt muốn nhấn mạnh. Nếu bạn dùng fs.mkdirSync() để tạo thư mục mỗi khi có một request đến server, server của bạn sẽ "đứng hình" và không thể xử lý các request khác cho đến khi tác vụ tạo thư mục hoàn thành. Hãy dùng fs.mkdir() hoặc fs.promises.mkdir() để xử lý bất đồng bộ, giữ cho server "mượt mà" như lụa. Nhớ kỹ, "sức mạnh đi kèm trách nhiệm"! Hiểu rõ công cụ của mình sẽ giúp bạn trở thành một "dev xịn xò" hơn. Giờ thì, "triển" thôi nào! 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é!

40 Đọc tiếp
fs.mkdir(): 'Xây Nhà' Cho App Node.js Của Gen Z
20/03/2026

fs.mkdir(): 'Xây Nhà' Cho App Node.js Của Gen Z

Anh em Gen Z thân mến, hôm nay anh Creyt sẽ dẫn dắt chúng ta đi "xây nhà" cho ứng dụng Node.js của mình. Nghe thì có vẻ "hàn lâm" nhưng thực ra nó là một trong những kỹ năng "sinh tồn" cơ bản nhất của một "thợ code" chính hiệu đấy! 🏗️ fs.mkdir(): Kiến Trúc Sư Của Thư Mục Bạn cứ hình dung thế này: Ứng dụng của bạn giống như một căn nhà "full nội thất" vậy. Nhưng để căn nhà đó hoạt động trơn tru, bạn cần có những "căn phòng" (thư mục) để chứa "đồ đạc" (các file ảnh, file log, file dữ liệu...). Mà "đồ đạc" thì đâu thể cứ vứt lung tung được, phải không? fs.mkdir() chính là kiến trúc sư trưởng của bạn trong Node.js, chuyên trách nhiệm vụ tạo ra các thư mục mới trong hệ thống file. Nó nằm trong module fs (File System) – bộ công cụ "quản lý nhà cửa" mạnh mẽ của Node.js. Để làm gì ư? Đơn giản là để: Tổ chức dữ liệu: Tách riêng ảnh của user này vào thư mục riêng, log của ngày hôm nay vào thư mục khác. Giúp mọi thứ ngăn nắp, dễ tìm, dễ quản lý. Lưu trữ file tạm: Tạo nơi chứa các file "tạm trú" trong quá trình xử lý. Cấu trúc dự án động: Khi bạn cần tạo ra các cấu trúc thư mục đặc thù dựa trên logic của ứng dụng. 🛠️ Code Ví Dụ: Bắt Tay Vào Xây Dựng Giờ thì "xắn tay áo" lên và "xây" thôi! Anh Creyt sẽ "tặng" các bạn vài "bản vẽ" (code ví dụ) chuẩn chỉnh nhất. 1. Dùng Callback (Kiểu truyền thống – hơi "cổ" nhưng vẫn chạy tốt) Đây là cách bạn "giao việc" cho fs.mkdir() và "chờ điện thoại" (callback) báo lại khi việc xong hoặc có lỗi. const fs = require('fs'); const folderName = './myNewFolderCallback'; fs.mkdir(folderName, (err) => { if (err) { if (err.code === 'EEXIST') { console.error(`Thư mục '${folderName}' đã tồn tại rồi, anh bạn!`); } else { console.error('Ối giời ơi, có lỗi rồi:', err); } return; } console.log(`Đã xây xong thư mục '${folderName}' một cách ngon lành!`); }); Giải thích: Chúng ta truyền tên thư mục và một hàm callback. Hàm này sẽ được gọi khi mkdir hoàn thành hoặc gặp lỗi. err.code === 'EEXIST' là "mã lỗi" khi thư mục bạn muốn tạo đã có sẵn. Rất quan trọng để kiểm tra! 2. Dùng Promises (Kiểu hiện đại – phong cách Gen Z) Đây là cách anh Creyt khuyến khích các bạn dùng. Nó "sáng sủa" hơn rất nhiều, đặc biệt khi dùng với async/await. Cứ như bạn "đặt hàng online" vậy: đặt xong là xong, không cần chờ đợi "tại chỗ", khi nào có kết quả thì ứng dụng của bạn "nhận thông báo". const fs = require('fs').promises; // Lưu ý: dùng fs.promises async function createFolderAsync(folderName) { try { await fs.mkdir(folderName); console.log(`Đã xây xong thư mục '${folderName}' bằng Promise/async-await!`); } catch (err) { if (err.code === 'EEXIST') { console.error(`Thư mục '${folderName}' đã tồn tại, không cần xây lại.`); } else { console.error('Đã có một sự cố xây dựng:', err); } } } createFolderAsync('./myNewFolderPromise'); createFolderAsync('./myNewFolderPromise'); // Thử tạo lại để xem lỗi EEXIST Giải thích: Chúng ta dùng require('fs').promises để lấy phiên bản Promise của các hàm fs. async/await giúp code đọc tuần tự hơn, dù bên dưới nó vẫn là bất đồng bộ. try...catch là "đội bảo hiểm" của bạn, giúp bắt các lỗi xảy ra trong quá trình "xây dựng". 3. Tạo Thư Mục Lồng Nhau (Recursive – "Xây chung cư" một phát ăn ngay) Nếu bạn muốn tạo một chuỗi thư mục như uploads/2023/10/images, bạn không cần tạo từng cái một. Chỉ cần thêm recursive: true! const fs = require('fs').promises; async function createNestedFolders(path) { try { await fs.mkdir(path, { recursive: true }); console.log(`Đã tạo toàn bộ 'chung cư' tại '${path}' thành công!`); } catch (err) { console.error('Lỗi khi xây chung cư:', err); } } createNestedFolders('./uploads/2024/01/avatars'); Giải thích: Option { recursive: true } là "siêu năng lực" giúp mkdir tạo tất cả các thư mục cha mẹ nếu chúng chưa tồn tại. Tuyệt vời ông mặt trời! 4. fs.mkdirSync() (Cẩn thận kẻo "tắc đường" app) Đây là phiên bản đồng bộ. Tức là, ứng dụng của bạn sẽ đứng yên chờ đợi cho đến khi thư mục được tạo xong mới làm việc khác. Trong môi trường server Node.js, điều này giống như "giao thông tắc nghẽn" vậy, làm chậm cả hệ thống. Hạn chế dùng trừ khi bạn thực sự hiểu rõ và chấp nhận rủi ro. const fs = require('fs'); try { fs.mkdirSync('./mySyncFolder'); console.log('Đã tạo thư mục đồng bộ ngon lành.'); } catch (err) { if (err.code === 'EEXIST') { console.error('Thư mục đồng bộ đã có.'); } else { console.error('Lỗi khi tạo thư mục đồng bộ:', err); } } 💡 Mẹo "Sống Còn" & Best Practices Từ Anh Creyt Để trở thành một "thợ code" chuyên nghiệp, đừng quên những mẹo này: "Tối ưu hóa công trường" với async/await: Luôn ưu tiên dùng fs.promises.mkdir() kết hợp async/await. Code của bạn sẽ "sáng sủa", dễ đọc và dễ bảo trì hơn rất nhiều. Hạn chế callback "rườm rà" và Sync "gây tắc nghẽn". "Đội bảo hiểm" try...catch: Luôn luôn bọc các thao tác fs trong try...catch (hoặc xử lý lỗi trong callback). Bạn không muốn ứng dụng của mình "sập" chỉ vì một lỗi tạo thư mục nhỏ nhặt đâu. "Kiểm tra hiện trạng" EEXIST: Khi tạo thư mục, hãy luôn kiểm tra lỗi EEXIST. Nếu thư mục đã tồn tại, thường thì bạn không cần làm gì cả, hoặc đơn giản là báo lại cho người dùng biết. "Xây chung cư tự động" với recursive: true: Khi cần tạo nhiều thư mục lồng nhau, đừng ngần ngại dùng { recursive: true }. Nó sẽ giúp bạn tiết kiệm "công sức" viết code rất nhiều. "Suy nghĩ trước khi 'xây'": Trước khi tạo một thư mục, hãy tự hỏi: "Thư mục này dùng để làm gì? Tên có rõ ràng không? Có cần thiết không?". Tránh tạo ra các thư mục "rác" làm lộn xộn hệ thống. 🌍 Ứng Dụng Thực Tế: fs.mkdir() "Làm Được Gì"? Bạn sẽ thấy fs.mkdir() xuất hiện "khắp mọi nơi" trong các ứng dụng thực tế: Hệ thống upload file (Facebook, Instagram, Google Drive): Khi bạn upload ảnh, video, hệ thống có thể tạo các thư mục riêng biệt cho từng người dùng, hoặc theo ngày tháng để dễ quản lý. Ví dụ: uploads/user_id/images/, uploads/2023/10/videos/. Hệ thống cache dữ liệu: Các ứng dụng web thường tạo thư mục cache để lưu trữ các tài nguyên tĩnh (CSS, JS, hình ảnh đã nén) nhằm tăng tốc độ tải trang. Ghi log hệ thống (Server logs): Các server thường tạo thư mục log theo ngày (ví dụ: logs/2023-10-27.log) hoặc theo loại log để dễ dàng theo dõi và debug. Công cụ dòng lệnh (CLI Tools): Khi bạn chạy các lệnh như npm init hoặc create-react-app, chúng sẽ tạo ra một cấu trúc thư mục dự án mới tinh cho bạn. Đó chính là fs.mkdir() đang "làm việc" đấy! 🧪 Thử Nghiệm & Nên Dùng Cho Case Nào? Thử nghiệm đã từng: Anh Creyt từng dùng fs.mkdir() để tự động tạo cấu trúc thư mục cho các dự án mới của mình. Chỉ cần chạy một script, là có ngay "căn nhà" với đầy đủ "phòng khách, phòng ngủ" (src, public, controllers, models...) mà không cần click chuột tay bo. Tiết kiệm thời gian "khởi công" cực kỳ! Nên dùng cho case nào? Quản lý file người dùng: Bất cứ khi nào bạn cần một nơi riêng để lưu trữ tài liệu, ảnh, video của từng người dùng trên server. Tổ chức dữ liệu động: Khi ứng dụng của bạn cần tạo ra các thư mục để phân loại dữ liệu theo tiêu chí nào đó (ví dụ: theo loại sản phẩm, theo ngày, theo trạng thái). Tạo môi trường làm việc: Khi bạn cần khởi tạo một môi trường hoặc cấu trúc file nhất định cho một tác vụ nào đó (ví dụ: thư mục tạm cho quá trình xử lý ảnh, thư mục output cho file nén). Nhớ nhé, fs.mkdir() không chỉ là một lệnh đơn thuần, nó là "nền móng" cho một hệ thống file được tổ chức "khoa học" và "bền vững". Hãy thực hành thật nhiều để "nắm chắc trong tay" công cụ "xây dựng" này, anh em Gen Z nhé! 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é!

43 Đọc tiếp
fs.promises.readdir(): Radar quét kho báu trong Node.js
20/03/2026

fs.promises.readdir(): Radar quét kho báu trong Node.js

Chào các "coder nhí" tương lai, hay đúng hơn là "phù thủy code" thế hệ mới! Anh Creyt đây, hôm nay chúng ta sẽ cùng "đào bới" một công cụ cực kỳ "xịn xò" trong Node.js, đó là fs.promises.readdir(). Nghe tên có vẻ hơi "học thuật" đúng không? Đừng lo, anh sẽ "phiên dịch" nó ra ngôn ngữ Gen Z dễ hiểu nhất. 1. fs.promises.readdir() là gì mà "hot" thế? "Ngày xửa ngày xưa", khi các ứng dụng còn "ngây thơ", việc đọc danh sách file trong một thư mục giống như bạn mò mẫm trong một căn phòng tối đen, phải chờ từng món đồ hiện ra. Nhưng giờ đây, với fs.promises.readdir(), mọi thứ đã "lên level" rồi! Hãy hình dung thế này: Thư mục của bạn là một "hang động bí mật" chứa đầy "kho báu" (các file và thư mục con). fs.promises.readdir() chính là "chiếc radar quét kho báu" siêu hiện đại của bạn. Nó không chỉ quét mà còn trả về danh sách tất cả "kho báu" trong "hang động" đó một cách nhanh như chớp và không làm tắc nghẽn công việc chính của bạn. Tại sao lại nhanh như chớp? Vì nó dùng "promises" – một cơ chế bất đồng bộ (asynchronous) giúp Node.js không phải "đứng đợi" mà có thể làm nhiều việc cùng lúc, y như bạn vừa chat Zalo vừa lướt TikTok vậy! Tóm lại: fs.promises.readdir() là một hàm trong module fs.promises của Node.js, dùng để đọc và trả về một mảng chứa tên tất cả các file và thư mục con có trong một thư mục cụ thể. Vì nó trả về một Promise, nên chúng ta thường dùng async/await để code "mượt mà" và dễ đọc hơn, tránh "callback hell" mà các "tiền bối" ngày xưa hay gặp phải. 2. Code Ví Dụ Minh Họa: "Thực hành là chân lý!" Giờ thì "xắn tay áo" vào code thôi. Anh sẽ cho các bạn xem cách chiếc radar này hoạt động. Ví dụ 1: Quét kho báu trong thư mục hiện tại Giả sử bạn có cấu trúc thư mục như sau: my-project/ ├── index.js ├── data/ │ ├── users.json │ └── products.csv └── utils.js Và bạn muốn đọc nội dung thư mục my-project (nơi index.js đang chạy): // index.js const { readdir } = require('fs').promises; const path = require('path'); async function listDirectoryContents(directoryPath) { try { const files = await readdir(directoryPath); // 'Quét' thư mục console.log(` Kho báu trong hang động '${directoryPath}':`); for (const file of files) { console.log(`- ${file}`); // In ra từng 'kho báu' } } catch (err) { console.error(` Ối! Radar bị nhiễu sóng khi quét '${directoryPath}':`, err); } } // Quét thư mục hiện tại listDirectoryContents('./'); // Hoặc quét một thư mục con cụ thể listDirectoryContents('./data'); Khi chạy node index.js, bạn sẽ thấy output đại loại như: Kho báu trong hang động './': - index.js - data - utils.js Kho báu trong hang động './data': - users.json - products.csv Ví dụ 2: Lọc "kho báu" theo loại (file hay folder)? Đôi khi bạn muốn biết rõ hơn về từng "kho báu" (nó là file hay folder). readdir có một option "xịn sò" tên là withFileTypes: true. const { readdir } = require('fs').promises; const path = require('path'); async function listDetailedContents(directoryPath) { try { // 'Quét' với option để biết loại 'kho báu' const dirents = await readdir(directoryPath, { withFileTypes: true }); console.log(` Phân loại kho báu trong hang động '${directoryPath}':`); for (const dirent of dirents) { if (dirent.isDirectory()) { console.log(`[FOLDER] ${dirent.name}`); } else if (dirent.isFile()) { console.log(`[FILE] ${dirent.name}`); } else { console.log(`[KHÁC] ${dirent.name}`); // Ví dụ: symbolic link } } } catch (err) { console.error(` Radar bị lỗi khi phân loại kho báu trong '${directoryPath}':`, err); } } listDetailedContents('./'); Output sẽ có dạng: Phân loại kho báu trong hang động './': [FILE] index.js [FOLDER] data [FILE] utils.js 3. Mẹo (Best Practices) để "hack" hiệu quả hơn! Anh Creyt có vài "chiêu" bỏ túi để các bạn dùng readdir "thần sầu" hơn: "Bất đồng bộ hóa" là chân ái: Luôn luôn ưu tiên dùng fs.promises.readdir() thay vì fs.readdir() truyền thống. Dùng async/await làm code của bạn "sáng sủa" như đèn pha ô tô, dễ đọc, dễ bảo trì, và tránh "callback hell" ám ảnh. Đừng bao giờ quay lại "thời đồ đá" với callback nữa nhé! "Bình chữa cháy" try...catch: Không phải lúc nào đường đi cũng "phẳng lì". Thư mục có thể không tồn tại, hoặc bạn không có quyền truy cập. Luôn luôn "thủ sẵn" try...catch để "dập lửa" khi có lỗi xảy ra. Nếu không, app của bạn sẽ "bay màu" ngay lập tức đấy! Đường dẫn "chuẩn chỉ" với path.join: Đừng bao giờ tự nối chuỗi để tạo đường dẫn file/thư mục. Hãy dùng path.join() để đảm bảo đường dẫn của bạn hoạt động "ngon lành cành đào" trên mọi hệ điều hành (Windows dùng \, Linux/macOS dùng /). withFileTypes: true - "Biết người biết ta, trăm trận trăm thắng": Nếu bạn cần phân biệt đâu là file, đâu là folder, hãy dùng option này. Nó giúp bạn có thông tin chi tiết hơn mà không cần phải gọi thêm stat() cho từng item, tiết kiệm tài nguyên và thời gian. Cẩn thận với thư mục "khổng lồ": Quét một thư mục chứa hàng ngàn, thậm chí hàng triệu file/folder có thể tốn rất nhiều tài nguyên và thời gian. Hãy cân nhắc kỹ hoặc tìm cách tối ưu (ví dụ: chỉ quét một phần, dùng lazy loading) nếu bạn phải làm việc với các thư mục "quá khổ" như vậy. Nó giống như bạn quét cả một kho vũ khí vậy, phải có chiến thuật rõ ràng! 4. Ứng dụng thực tế: "Radar" này dùng ở đâu? fs.promises.readdir() không chỉ là lý thuyết, nó được ứng dụng "rộng rãi" trong thế giới thực: File Explorers / Hệ thống quản lý nội dung (CMS): Các ứng dụng như Netlify CMS, Strapi, hoặc thậm chí là giao diện quản lý file trên server của bạn, đều cần readdir để hiển thị danh sách file và thư mục cho người dùng. Build Tools (Webpack, Gulp, Vite): Khi bạn build một dự án, các công cụ này cần "quét" qua các thư mục src để tìm tất cả các file mã nguồn (JavaScript, CSS, ảnh...) để nén, biên dịch, hoặc tối ưu hóa. Static Site Generators (Next.js, Gatsby, Astro): Các framework này thường đọc các file Markdown hoặc JSON trong một thư mục cụ thể để tự động tạo ra các trang web tĩnh. Ví dụ, đọc tất cả các file .md trong thư mục posts để tạo ra các bài blog. APIs phục vụ download/upload file: Một API cho phép người dùng download các file đã có sẵn trên server thường dùng readdir để liệt kê các file đó trước khi gửi cho client. 5. Thử nghiệm và Nên dùng cho case nào? Thử nghiệm: Để "nắm bắt" nó tốt hơn, bạn hãy: Tạo một thư mục mới, ví dụ test-folder. Bên trong test-folder, tạo vài file (ví dụ: a.txt, b.json) và vài thư mục con (ví dụ: sub-folder1, sub-folder2). Trong sub-folder1, tạo thêm một file c.js. Chạy code ví dụ của anh để quét test-folder và test-folder/sub-folder1. Quan sát output và thử các option khác nhau. Thử quét một thư mục không tồn tại hoặc bạn không có quyền truy cập để xem cách try...catch "cứu nguy" như thế nào. Nên dùng fs.promises.readdir() khi: Bạn cần hiển thị danh sách file/thư mục lên giao diện người dùng (dashboard, quản lý file). Bạn muốn xử lý hàng loạt file trong một thư mục (ví dụ: đổi tên tất cả file ảnh, xóa các file tạm). Bạn cần tạo cấu trúc thư mục động hoặc kiểm tra sự tồn tại của các tài nguyên dựa trên danh sách file/thư mục. Bạn đang xây dựng một ứng dụng backend cần tương tác với hệ thống file của server để đọc/ghi các tài nguyên. Không nên dùng fs.promises.readdir() khi: Bạn chỉ cần đọc nội dung của một file cụ thể (hãy dùng fs.promises.readFile()). Bạn chỉ cần kiểm tra sự tồn tại của một file hoặc thư mục mà không cần danh sách bên trong (hãy dùng fs.promises.access()). Vậy đó, fs.promises.readdir() không chỉ là một công cụ, nó là "chiếc radar" giúp bạn "thám hiểm" và "quản lý" thế giới file của Node.js một cách "thông minh" và "hiệu quả" hơn. Hãy "cầm lấy" nó và bắt đầu "khám phá" những điều thú vị nhé! Chúc các bạn code "mượt mà"! 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é!

42 Đọc tiếp
fs.promises.writeFile(): Bậc thầy lưu trữ của dân code Gen Z!
20/03/2026

fs.promises.writeFile(): Bậc thầy lưu trữ của dân code Gen Z!

Chào các "coder nhí" tương lai và hiện tại của Node.js! Anh Creyt lại lên sóng đây. Hôm nay, chúng ta sẽ "mổ xẻ" một "công cụ" cực kỳ quyền năng trong bộ "đồ nghề" của dân lập trình, đặc biệt là khi các em làm việc với Node.js: chính là fs.promises.writeFile(). Nghe tên dài ngoằng vậy thôi chứ "công năng" của nó thì bá đạo lắm! 1. fs.promises.writeFile() là gì mà Gen Z phải biết? "fs" ở đây viết tắt của File System, tức là hệ thống file. "promises" thì như các em biết, nó là lời hứa, là cam kết sẽ hoàn thành một tác vụ nào đó trong tương lai mà không làm "treo" máy. Còn "writeFile" thì đơn giản là "viết vào file". Ghép lại, fs.promises.writeFile() chính là "Thư ký tốc ký siêu đẳng" của Node.js, chuyên nhận nhiệm vụ ghi dữ liệu vào một file nào đó một cách bất đồng bộ. Em hình dung thế này: Em là một đầu bếp (chương trình Node.js của em), đang bận rộn làm món ăn (xử lý các tác vụ khác). Bỗng dưng, em cần ghi lại công thức mới vào cuốn sổ tay (ghi dữ liệu vào file). Nếu em tự mình dừng mọi thứ lại để ngồi viết từng chữ (tác vụ đồng bộ - fs.writeFileSync), thì món ăn sẽ nguội mất, khách hàng sẽ "quay xe". Nhưng với fs.promises.writeFile(), em chỉ cần nói với "trợ lý ảo" (cái Promise) của mình: "Ê, ghi giúp anh cái công thức này vào file mon_moi.txt nhé!". Trợ lý sẽ nhận lệnh và âm thầm làm việc của mình, trong khi em vẫn tiếp tục "xào nấu" các món khác. Khi trợ lý làm xong, nó sẽ "báo cáo" lại cho em biết là thành công hay thất bại. Tuyệt vời không? Tóm lại, nó dùng để: Ghi nội dung (chuỗi, buffer) vào một file cụ thể trên ổ đĩa. Điểm mấu chốt là bất đồng bộ, giúp ứng dụng của em luôn mượt mà, không bị "đứng hình" khi đang ghi file, đặc biệt quan trọng với các ứng dụng web, API server. 2. Code Ví Dụ Minh Hoạ: "Viết là phải có code!" Thôi lý thuyết suông mãi chán lắm, anh em mình vào "thực chiến" luôn. Để dùng fs.promises, đầu tiên các em phải "import" nó vào đã: import { writeFile } from 'fs/promises'; // Cách hiện đại dùng ES Modules // Hoặc nếu dùng CommonJS: // const { writeFile } = require('fs').promises; async function ghiDuLieuVaoFile() { const tenFile = 'thong_tin_genz.txt'; const duLieu = 'Tên: Nguyễn Văn A\nTuổi: 18\nSở thích: Code, TikTok, Game'; try { await writeFile(tenFile, duLieu); console.log(`✅ Đã ghi dữ liệu thành công vào file: ${tenFile}`); } catch (error) { console.error('❌ Lỗi khi ghi file:', error.message); } } ghiDuLieuVaoFile(); Giải thích nhanh: import { writeFile } from 'fs/promises';: Chúng ta lấy hàm writeFile từ module fs/promises. async function ghiDuLieuVaoFile(): Vì writeFile trả về một Promise, chúng ta cần dùng async/await để xử lý nó một cách tuần tự (nhưng vẫn bất đồng bộ ở nền). await writeFile(tenFile, duLieu);: Đây là "phép thuật" chính! Nó sẽ ghi duLieu vào tenFile. Chương trình sẽ "đợi" cho đến khi tác vụ ghi file hoàn tất rồi mới đi tiếp, nhưng quan trọng là nó không chặn các tác vụ khác chạy song song. try...catch: "Bảo hiểm" của chúng ta. Nếu có bất kỳ lỗi nào xảy ra trong quá trình ghi file (ví dụ: không có quyền ghi, đường dẫn sai, ổ đĩa đầy), catch sẽ "tóm" lấy lỗi đó và chúng ta có thể xử lý nó. Ví dụ nâng cao hơn một chút: Ghi một đối tượng JSON import { writeFile } from 'fs/promises'; async function ghiJsonObjectVaoFile() { const tenFileJson = 'cau_hinh_app.json'; const cauHinh = { appName: 'GenZ_ChatApp', version: '1.0.0', debugMode: true, users: ['creyt', 'alice', 'bob'] }; try { // JSON.stringify để chuyển object thành chuỗi JSON await writeFile(tenFileJson, JSON.stringify(cauHinh, null, 2)); console.log(`✅ Đã ghi đối tượng JSON thành công vào file: ${tenFileJson}`); } catch (error) { console.error('❌ Lỗi khi ghi file JSON:', error.message); } } ghiJsonObjectVaoFile(); JSON.stringify(cauHinh, null, 2): Dùng để chuyển đối tượng JavaScript thành chuỗi JSON. Tham số null, 2 giúp format JSON đẹp hơn với 2 khoảng trắng thụt đầu dòng, dễ đọc hơn khi mở file. 3. Mẹo (Best Practices) từ "lão làng" Creyt Luôn await và try...catch: Nhắc lại lần nữa: Đừng bao giờ quên! Ghi file là một tác vụ I/O (Input/Output), nó phụ thuộc vào ổ cứng, hệ điều hành, quyền hạn... nên rất dễ "fail". await đảm bảo bạn biết khi nào tác vụ xong, try...catch giúp bạn "sống sót" khi nó "fail". Coi như là "áo giáp" và "bộ đàm" của em vậy. Encoding (Mã hóa): Mặc định writeFile 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 là khi các em làm việc với tiếng Việt có dấu. Trừ khi có yêu cầu đặc biệt, cứ để utf8 mà "chiến". Đường dẫn file: Nên dùng path.join từ module path để xây dựng đường dẫn file, đặc biệt khi deploy lên các hệ điều hành khác nhau (Windows dùng \, Linux/macOS dùng /). Điều này giúp code của em "thân thiện" hơn với mọi môi trường. import { writeFile } from 'fs/promises'; import path from 'path'; const tenFileLog = 'app.log'; const duongDanTuyetDoi = path.join(__dirname, 'logs', tenFileLog); // Ghi file vào thư mục 'logs' trong cùng thư mục với file script hiện tại await writeFile(duongDanTuyetDoi, 'Nội dung log...'); Lưu ý: __dirname chỉ có trong CommonJS. Với ES Modules, các em dùng import.meta.url và path.dirname(fileURLToPath(import.meta.url)). writeFile vs writeFileSync: Hiểu rõ sự khác biệt. writeFile (của fs.promises hoặc fs callback) là bất đồng bộ, phù hợp cho mọi ứng dụng cần hiệu suất, không chặn luồng chính. writeFileSync là đồng bộ, nó sẽ "đứng đợi" cho đến khi ghi xong mới làm việc khác. Chỉ dùng writeFileSync cho các script nhỏ, tác vụ khởi tạo mà việc chặn luồng không gây ảnh hưởng lớn, hoặc khi bạn muốn nó chặn. 4. Ứng dụng thực tế: "Xem ai đã xài rồi?" fs.promises.writeFile() được dùng "nhan nhản" trong các ứng dụng Node.js lớn nhỏ: Hệ thống Log: Ghi lại các sự kiện, lỗi, hoạt động của người dùng vào các file log. Ví dụ: một server web ghi lại mọi request HTTP, lỗi 500, hay các hành động quan trọng của admin. Lưu Cache dữ liệu: Các ứng dụng có thể lưu trữ kết quả của các truy vấn database phức tạp hoặc dữ liệu từ API bên ngoài vào file để lần sau đọc nhanh hơn, giảm tải cho server gốc. Ví dụ: một trang tin tức lưu cache các bài viết hot ra file JSON để load nhanh hơn. Export báo cáo/dữ liệu: Khi người dùng muốn tải xuống một báo cáo dưới dạng CSV, Excel, hoặc JSON. Server sẽ "chế biến" dữ liệu và dùng writeFile để tạo file đó. Quản lý cấu hình: Tự động tạo hoặc cập nhật các file cấu hình .json hay .env cho ứng dụng dựa trên các tham số đầu vào. 5. Thử nghiệm của Creyt & Khi nào nên dùng? Anh Creyt đã "chinh chiến" với Node.js bao năm, và fs.promises.writeFile() là một người bạn "thân thiết" không thể thiếu. Anh đã dùng nó từ việc ghi hàng triệu dòng log mỗi ngày cho đến việc tạo ra các file dữ liệu khổng lồ để phân tích. Nên dùng fs.promises.writeFile() khi: Xây dựng ứng dụng web/API server: Đây là "kim chỉ nam"! Em không bao giờ muốn server của mình bị "treo" vì một tác vụ ghi file. Bất đồng bộ là chìa khóa để server phản hồi nhanh, xử lý nhiều yêu cầu cùng lúc. Xử lý file có dung lượng lớn: Ghi file vài MB hay vài GB mà không làm "đứng" toàn bộ ứng dụng? writeFile chính là giải pháp. Code sạch sẽ, hiện đại: Với async/await, code của em sẽ dễ đọc, dễ bảo trì hơn rất nhiều so với việc dùng callback "lồng đèn". Khi hiệu suất là ưu tiên hàng đầu: Nếu ứng dụng của em cần hoạt động trơn tru, không gián đoạn, hãy nghĩ ngay đến promises API. Không nhất thiết phải dùng fs.promises.writeFile() (hoặc có thể dùng writeFileSync) khi: Script tiện ích nhỏ, chạy một lần: Các script chỉ chạy một lần, không yêu cầu độ phản hồi tức thì, việc dùng writeFileSync có thể đơn giản hơn (ít code hơn vì không cần async/await và try...catch phức tạp). Trong quá trình khởi tạo ứng dụng: Ví dụ, ghi một file cấu hình mặc định chỉ một lần khi ứng dụng vừa khởi động. Việc này thường không ảnh hưởng đến trải nghiệm người dùng. Nhớ nhé, các em Gen Z! Nắm vững fs.promises.writeFile() là các em đã có thêm một "siêu năng lực" để điều khiển file trong Node.js rồi đấy. Cứ thực hành nhiều vào, có gì thắc mắc cứ "hú" anh Creyt! 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é!

42 Đọc tiếp
fs.promises.readFile(): Thám Tử File Của Gen Z – Đọc Nhanh, Đọc Gọn!
20/03/2026

fs.promises.readFile(): Thám Tử File Của Gen Z – Đọc Nhanh, Đọc Gọn!

Chào các "cú đêm" Gen Z! Creyt đây, hôm nay chúng ta sẽ cùng "mổ xẻ" một "thám tử" cực kỳ "cool ngầu" trong thế giới Node.js: fs.promises.readFile(). fs.promises.readFile() là gì? Để làm gì? Thử tưởng tượng thế này nhé: Bạn có một "kho báu" thông tin được cất giấu trong một "cuốn sách thần kỳ" (file) trên máy tính. Nhiệm vụ của bạn là đọc toàn bộ nội dung cuốn sách đó. Hồi xưa, các "pháp sư" Node.js thường phải dùng phép thuật "callback" để đọc từng trang một, rồi chờ đợi mòn mỏi, đôi khi còn lạc vào "mê cung callback hell" rối rắm. Nhưng với fs.promises.readFile(), mọi chuyện trở nên "EZ game" hơn nhiều! Nó giống như một "thám tử siêu năng lực" có khả năng "quét" toàn bộ cuốn sách đó trong tích tắc, gom tất cả thông tin lại thành một "gói" duy nhất, rồi "báo cáo" cho bạn một lần duy nhất khi đã xong xuôi. Và đặc biệt hơn, anh chàng thám tử này làm việc "bất đồng bộ" (asynchronous) - nghĩa là trong lúc anh ta đang "quét sách", bạn vẫn có thể "lướt TikTok" hoặc làm những việc khác mà ứng dụng của bạn không hề "đứng hình" chờ đợi. Nói tóm lại, fs.promises.readFile() là cách "hiện đại", "sành điệu" để đọc toàn bộ nội dung của một file vào bộ nhớ (RAM) trong Node.js, sử dụng cú pháp Promise "mượt mà" (kết hợp với async/await là "hết nước chấm"). Nó trả về một Promise, một "lời hứa" rằng "tôi sẽ trả về dữ liệu khi tôi đọc xong, hoặc tôi sẽ báo lỗi nếu có gì đó sai". Code Ví Dụ Minh Họa Rõ Ràng Để "thực chiến" với fs.promises.readFile(), đầu tiên bạn cần có một file để đọc. Hãy tạo một file tên là du_lieu_quan_trong.txt với nội dung bất kỳ (ví dụ: Chào các Gen Z! Đây là bài học của thầy Creyt về fs.promises.readFile.). # Trong terminal, tạo file này echo "Chào các Gen Z! Đây là bài học của thầy Creyt về fs.promises.readFile." > du_lieu_quan_trong.txt Giờ thì chúng ta sẽ viết code Node.js để đọc file này: // Bước 1: Import module fs.promises // Nhớ là .promises nhé, đây là phiên bản trả về Promise! const fs = require('fs').promises; async function docFileThanToc() { try { console.log("Thám tử Creyt đang bắt đầu đọc file..."); // Bước 2: Gọi fs.readFile() với async/await // Tham số thứ hai là encoding, 'utf8' là phổ biến nhất cho văn bản tiếng Việt/Anh const noiDungFile = await fs.readFile('du_lieu_quan_trong.txt', { encoding: 'utf8' }); console.log("Thám tử Creyt đã đọc xong! Đây là nội dung:"); console.log(noiDungFile); // Bước 3: Thử đọc một file không tồn tại để xem cách xử lý lỗi console.log("\nThử đọc file không tồn tại để xem lỗi nó như nào nhé..."); const fileMa = await fs.readFile('file_khong_ton_tai.txt', { encoding: 'utf8' }); console.log(fileMa); // Dòng này sẽ không bao giờ chạy nếu file không có } catch (error) { // Bước 4: Xử lý lỗi nếu có console.error("Ối! Thám tử Creyt gặp trục trặc khi đọc file rồi:", error.message); if (error.code === 'ENOENT') { console.error("Có vẻ như file bạn muốn đọc không hề tồn tại. Kiểm tra lại đường dẫn nhé!"); } } finally { // Bước 5: Luôn chạy sau cùng, dù thành công hay thất bại console.log("\nCông việc đọc file đã kết thúc, dù thành công hay thất bại!"); } } // Chạy hàm đọc file docFileThanToc(); // --- Cú pháp với .then().catch() cũng rất "ổn áp" nhé! --- console.log("\n--- Dùng .then().catch() thì sao? ---"); fs.readFile('du_lieu_quan_trong.txt', 'utf8') .then(data => { console.log("Đã đọc xong bằng .then().catch():"); console.log(data); }) .catch(err => { console.error("Lỗi rồi bạn ơi (từ .then().catch()):", err.message); }); Mẹo (Best Practices) Để Ghi Nhớ và Dùng Thực Tế Luôn Luôn Bắt Lỗi (Error Handling): Trong thế giới lập trình, không phải lúc nào mọi thứ cũng "thuận buồm xuôi gió". File có thể không tồn tại, bạn không có quyền đọc, hoặc file bị hỏng. Hãy luôn dùng try...catch với async/await hoặc .catch() với Promise để "bọc" code của bạn. Đây là "tấm khiên" bảo vệ ứng dụng khỏi "sập nguồn" bất ngờ. Chỉ Định Encoding "Chuẩn Chỉ": File văn bản đâu phải lúc nào cũng là tiếng Anh. Để tránh "dấu hỏi" hay "ô vuông" khó hiểu xuất hiện trong nội dung đọc được, hãy luôn nói rõ bạn muốn đọc file với encoding nào (ví dụ: 'utf8' là "quốc dân" cho văn bản đa ngôn ngữ). Nếu không chỉ định, readFile sẽ trả về một Buffer (dạng chuỗi byte), lúc đó bạn lại phải tự decode, hơi "rối não" đấy. Cẩn Thận Với File "Khổng Lồ": fs.promises.readFile() sẽ "ôm" toàn bộ nội dung file vào bộ nhớ (RAM) của ứng dụng. Hãy tưởng tượng bạn đang cố gắng nhét cả một "thư viện quốc gia" vào một cái "balo học sinh" vậy. Nếu bạn đọc một file vài GB, RAM của bạn sẽ "kêu gào thảm thiết" và ứng dụng có thể "sập". Lúc đó, hãy nghĩ đến fs.createReadStream() - nó giống như việc "đọc từng trang một" thay vì "ôm cả cuốn sách", tiết kiệm bộ nhớ hơn rất nhiều. Ưu Tiên fs.promises: Nếu bạn đang code một ứng dụng Node.js mới toanh hoặc đang "tân trang" lại code cũ, hãy luôn dùng phiên bản promises của fs thay vì phiên bản callback truyền thống. Code của bạn sẽ "sáng sủa", "dễ thở" và dễ bảo trì hơn rất nhiều. Ví Dụ Thực Tế Các Ứng Dụng/Website Đã Ứng Dụng fs.promises.readFile() là một "công cụ" cơ bản nhưng cực kỳ quyền năng, được sử dụng trong vô số tình huống thực tế: Đọc file cấu hình (.env, config.json): Hầu hết các ứng dụng cần đọc các cài đặt ban đầu (như kết nối database, API keys) từ các file cấu hình nhỏ. readFile là lựa chọn lý tưởng cho các file này. Phục vụ nội dung tĩnh đơn giản: Nếu website của bạn có các trang HTML, CSS, JS nhỏ được lưu trữ dưới dạng file, bạn có thể dùng readFile để đọc chúng và gửi về trình duyệt. Tải template (mẫu): Khi bạn dùng các template engine (như EJS, Handlebars, Pug), chúng thường dùng readFile để đọc các file template .ejs hay .hbs trước khi render ra HTML cuối cùng. Đọc dữ liệu từ JSON/CSV nhỏ: Các file dữ liệu nhỏ dùng để lưu trữ thông tin không cần database phức tạp (ví dụ: danh sách các quốc gia, dữ liệu mock cho phát triển) cũng là một case lý tưởng để dùng readFile. Thử Nghiệm Đã Từng và Hướng Dẫn Nên Dùng Cho Case Nào Creyt đã từng "kinh qua" rất nhiều dự án, và đây là kinh nghiệm "xương máu" khi dùng fs.promises.readFile(): Nên dùng khi: Kích thước file nhỏ đến trung bình: (vài KB đến vài MB). Đây là "sân chơi" của readFile. Đọc các file cấu hình, file markdown, file log nhỏ, file ảnh thumbnail là những case hoàn hảo. Bạn cần toàn bộ nội dung file để xử lý một lần: Ví dụ, bạn cần parse một file JSON thành object, biên dịch một template HTML, hoặc nén/giải nén một file zip nhỏ. readFile sẽ "gom" hết dữ liệu rồi mới giao cho bạn xử lý. Bạn muốn code bất đồng bộ gọn gàng: Với async/await, code của bạn sẽ trông như đang đọc file một cách đồng bộ mà không hề block ứng dụng. "Đẹp trai" và "thông minh"! Không nên dùng khi: File có kích thước rất lớn: (vài chục MB trở lên, đến vài GB). Như đã nói ở trên, nó sẽ "ngốn" RAM và có thể làm crash ứng dụng của bạn. Lúc đó, hãy chuyển sang dùng fs.createReadStream() để xử lý file theo từng đoạn (chunk) một, giống như bạn đọc một cuốn sách dày theo từng chương vậy, không cần nhét cả cuốn vào đầu một lúc. Bạn chỉ cần đọc một phần của file: Nếu bạn chỉ muốn đọc vài dòng đầu hoặc một đoạn cụ thể trong file, readFile không phải là lựa chọn tối ưu vì nó vẫn đọc toàn bộ file. Trong trường hợp này, fs.createReadStream() hoặc các thư viện chuyên biệt có thể hiệu quả hơn. Hy vọng với bài học này, các bạn Gen Z đã "bỏ túi" được thêm một "siêu năng lực" nữa trong hành trình chinh phục Node.js. Nhớ thực hành và "vọc vạch" thật nhiều nhé! Hẹn gặp lại trong những bài học "chất như nước cất" tiếp theo! 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é!

41 Đọc tiếp
fs.appendFile(): Đỉnh cao ghi nhật ký, không sợ mất dữ liệu cũ!
19/03/2026

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

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? 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é! 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é!

44 Đọc tiếp
fs.writeFileSync(): Ghi Sổ Thần Tốc, Xong Việc Mới Tính!
19/03/2026

fs.writeFileSync(): Ghi Sổ Thần Tốc, Xong Việc Mới Tính!

Alo alo Gen Z code thủ! Hôm nay, Creyt sẽ đưa các bạn đi khám phá một "công cụ" siêu ngầu trong Node.js, đó là fs.writeFileSync(). Nghe tên có vẻ hơi 'hàn lâm' nhưng thực ra nó như một 'thủ thư khó tính' của hệ thống file vậy. Tưởng tượng bạn đang cần ghi chú một cái gì đó vào cuốn sổ tay ngay lập tức, không chần chừ, không suy nghĩ đến việc khác cho đến khi ghi xong. fs.writeFileSync() chính là cái 'sổ tay thần tốc' đó. Nó làm gì? Đơn giản là nó giúp bạn 'đổ mực' (ghi dữ liệu) vào một 'tờ giấy' (file) trên máy tính của bạn. Nếu tờ giấy đó chưa có, nó tạo ra. Nếu có rồi, nó sẽ ghi đè lên toàn bộ nội dung cũ. Và quan trọng nhất: nó làm điều đó đồng bộ (synchronously). 1. Code Ví Dụ: Ghi Chú 'Thần Tốc' Để dễ hình dung, ta có cái ví dụ 'mì ăn liền' sau: const fs = require('fs'); const filePath = './ghichu.txt'; const data = 'Hôm nay trời đẹp quá, nhớ học code nhé Gen Z!'; try { fs.writeFileSync(filePath, data); console.log('Ghi file thành công! Check file ghichu.txt đi nào.'); } catch (err) { console.error('Ối giời ơi, có lỗi khi ghi file rồi:', err); } // Ghi đè file nếu đã tồn tại const newData = 'Nội dung mới toanh, ghi đè cái cũ luôn!'; try { fs.writeFileSync(filePath, newData); console.log('Đã ghi đè file ghichu.txt với nội dung mới.'); } catch (err) { console.error('Lỗi khi ghi đè file:', err); } Và đây là một ví dụ có 'tâm' hơn, kèm theo 'bảo hiểm' lỗi (error handling) và 'tùy chọn' (options) encoding: const fs = require('fs'); const jsonFilePath = './cau_hinh.json'; const configData = { appName: 'GenZ_App', version: '1.0.0', settings: { theme: 'dark', notifications: true } }; try { // Ghi đối tượng JSON vào file, chuyển thành chuỗi trước fs.writeFileSync(jsonFilePath, JSON.stringify(configData, null, 2), { encoding: 'utf8', mode: 0o666, // Quyền đọc/ghi cho tất cả flag: 'w' // 'w' là viết (write), sẽ tạo file nếu không có, ghi đè nếu có }); console.log('Ghi file cấu hình thành công tại:', jsonFilePath); } catch (err) { console.error('Lỗi khi ghi file cấu hình:', err.message); } // Ví dụ về ghi file mà không có quyền const protectedPath = '/root/protected_file.txt'; // Thường cần quyền root const secretData = 'Đây là dữ liệu siêu bí mật!'; try { fs.writeFileSync(protectedPath, secretData); console.log('Ghi file bí mật thành công (chắc không đâu)'); } catch (err) { console.error(`Không thể ghi vào '${protectedPath}':`, err.message); console.error('Lỗi này thường do thiếu quyền truy cập.'); } 2. Creyt's Deep Dive: 'Sync' Là Gì Mà Nguy Hiểm Thế? Giờ, anh Creyt sẽ 'mổ xẻ' sâu hơn một chút về chữ 'sync' trong writeFileSync. Trong thế giới lập trình, 'đồng bộ' (synchronous) nghĩa là gì? Nó giống như bạn đang nấu cơm và chỉ có một cái bếp. Bạn phải nấu xong nồi cơm này, bắc ra, rồi mới có thể nấu món canh tiếp theo. Trong thời gian nồi cơm đang sôi, bạn không thể làm gì khác trên cái bếp đó. Với fs.writeFileSync(), khi bạn gọi nó, Node.js sẽ ngừng tất cả các công việc khác trên luồng chính (main thread) của ứng dụng bạn, đợi cho đến khi việc ghi file hoàn tất thì thôi. Chỉ khi ghi xong, nó mới 'thở phào' và cho phép các tác vụ khác chạy tiếp. Ưu điểm của sự 'khó tính' này: Đơn giản, dễ hiểu: Code chạy theo thứ tự bạn mong muốn, không cần lo nghĩ về callback hay async/await. Cứ gọi là nó làm, xong rồi mới đến dòng tiếp theo. An toàn trong kịch bản nhất định: Đảm bảo rằng file đã được ghi xong hoàn toàn trước khi code tiếp theo thực thi. Rất hữu ích cho việc ghi cấu hình hoặc các script nhỏ cần tính tuần tự cao. Nhược điểm (và tại sao nó lại 'nguy hiểm'): Block luồng chính (Main Thread Blocking): Đây là 'tử huyệt' của nó khi dùng trong môi trường server hiệu năng cao. Nếu bạn ghi một file lớn, ứng dụng của bạn sẽ 'đứng hình' trong thời gian đó, không thể xử lý các yêu cầu khác từ người dùng. Tưởng tượng một nhà hàng đang phục vụ khách, tự nhiên đầu bếp dừng hết mọi việc để... ghi công thức vào sổ! Khách sẽ 'bỏ chạy' hết. Không phù hợp với I/O nặng: Tránh xa khi cần ghi hàng loạt file, file lớn, hoặc trong các ứng dụng web cần phản hồi nhanh. Nó sẽ làm 'tắc nghẽn giao thông' và làm chậm ứng dụng của bạn đáng kể. 3. Mẹo Hay từ Creyt (Best Practices) Để dùng writeFileSync không 'gây họa', anh Creyt có vài 'mẹo vặt' sau: Luôn dùng try...catch: writeFileSync sẽ 'nổi cáu' (throw error) nếu có vấn đề (ví dụ: không có quyền ghi, đường dẫn sai). Hãy 'dỗ ngọt' nó bằng cách bọc trong try...catch để ứng dụng không 'sập nguồn' đột ngột. Cẩn thận với overwrite: Nhớ nhé, nó ghi đè! Nếu bạn muốn thêm nội dung vào cuối file mà không mất dữ liệu cũ, hãy dùng fs.appendFileSync() (hoặc fs.appendFile() cho async). Biết rõ khi nào nên dùng: Chỉ nên dùng cho các tác vụ ghi file nhỏ, không thường xuyên, hoặc trong các script độc lập mà việc blocking không ảnh hưởng đến trải nghiệm người dùng hoặc hiệu năng hệ thống. Suy nghĩ về encoding: Luôn chỉ định encoding (mặc định là utf8) để tránh các vấn đề về hiển thị ký tự đặc biệt, đặc biệt là với tiếng Việt. Khi nào thì 'say goodbye' với sync? Khi bạn xây dựng các ứng dụng web server, API cần xử lý nhiều yêu cầu đồng thời, hãy quay sang dùng fs.writeFile() (phiên bản bất đồng bộ) hoặc fs.promises.writeFile() để không làm 'tắc nghẽn giao thông' trên server. 4. Ứng Dụng Thực Tế: 'Thủ Thư Khó Tính' Làm Được Gì? Vậy thì, 'thủ thư khó tính' này được dùng ở đâu trong thế giới thực? Ghi file cấu hình (Configuration files): Khi một ứng dụng cần lưu lại cài đặt người dùng hoặc cấu hình hệ thống sau khi thay đổi (ví dụ: config.json). Vì việc này không xảy ra thường xuyên và cần đảm bảo ghi xong trước khi ứng dụng tiếp tục, writeFileSync là lựa chọn tốt. Ghi log đơn giản trong script: Các script chạy một lần, hoặc các tác vụ cron job cần ghi lại kết quả hoặc lỗi vào một file log nhỏ. Tạo file tạm thời: Khi cần tạo một file nhỏ để lưu trữ dữ liệu tạm thời trong quá trình xử lý của một script. Build tools/CLI tools: Các công cụ dòng lệnh thường dùng writeFileSync để tạo hoặc sửa đổi file trong quá trình build dự án (ví dụ: tạo file index.html động, ghi file package.json sau khi cài đặt dependency). 5. Thử Nghiệm & Nên Dùng Cho Case Nào? Creyt đã từng 'chinh chiến' với writeFileSync và rút ra vài kinh nghiệm xương máu: Nên dùng fs.writeFileSync() khi: Bạn đang viết một script Node.js chạy một lần để tự động hóa một tác vụ (ví dụ: đổi tên hàng loạt file, tạo báo cáo, nén ảnh). Bạn cần cập nhật một file .env hoặc config.json sau khi người dùng thay đổi cài đặt và muốn đảm bảo nó được ghi xong trước khi ứng dụng khởi động lại hoặc tiếp tục. Đây là lúc tính đồng bộ của nó trở thành ưu điểm. Trong các bài tập lập trình cơ bản, khi bạn muốn đơn giản hóa việc ghi file mà không cần quan tâm đến async/await phức tạp. Không nên dùng fs.writeFileSync() (và hãy dùng fs.writeFile hoặc fs.promises.writeFile) khi: Bạn đang xây dựng một Node.js web server (như Express, Koa) và cần ghi dữ liệu từ các yêu cầu của người dùng (ví dụ: upload file, lưu dữ liệu biểu mẫu, ghi log cho mỗi request). Bạn cần ghi một lượng lớn dữ liệu hoặc ghi vào nhiều file cùng lúc. Việc này sẽ gây 'treo' server của bạn. Ứng dụng của bạn yêu cầu phản hồi nhanh và không được phép bị 'đứng hình' dù chỉ một mili giây. Trong trường hợp này, việc 'ghi sổ thần tốc' có thể trở thành 'thần tốc gây sập nguồn' đấy! Nhớ nhé Gen Z, mỗi công cụ đều có công dụng riêng. Hiểu rõ bản chất của fs.writeFileSync() sẽ giúp bạn trở thành một 'code thủ' thông thái, biết khi nào nên dùng 'súng' và khi nào nên dùng 'dao'! 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é!

40 Đọc tiếp
fs.writeFile(): Thư Ký Đắc Lực Của Node.js Để Lưu Trữ Data
19/03/2026

fs.writeFile(): Thư Ký Đắc Lực Của Node.js Để Lưu Trữ Data

Mấy đứa Gen Z mê game, mê lưu thành quả đúng không? Trong lập trình cũng vậy, có lúc mình muốn lưu lại cái gì đó ra file để sau này dùng, hoặc để người khác đọc. Và cái "công cụ" thần thánh mà anh Creyt muốn giới thiệu hôm nay, chính là fs.writeFile() trong Node.js! 1. fs.writeFile() là gì? Để làm gì? Thử tưởng tượng thế này: code của mấy đứa chạy ầm ầm trên server, xử lý dữ liệu, tính toán tùm lum. Nhưng nếu server reboot cái là mọi thứ bay màu hết à? Xót xa không? fs.writeFile() (viết tắt của File System Write File) chính là "thư ký" riêng của mấy đứa trong Node.js. Nó nhận nhiệm vụ cực kỳ quan trọng: ghi nội dung vào một file trên ổ đĩa. Nói nôm na, nó giống như việc mấy đứa đang viết một bức thư tình (dữ liệu), rồi bảo một người đưa thư (Node.js) mang đến một địa chỉ cụ thể (tên file) và đặt nó vào đó. Nếu địa chỉ đó chưa có nhà (file chưa tồn tại), người đưa thư sẽ xây luôn một căn nhà mới rồi đặt thư vào. Còn nếu có nhà rồi, thì xin lỗi chủ nhà cũ nhé, bức thư mới sẽ ghi đè hoàn toàn lên bức thư cũ! Nhớ kỹ cái này nha, ghi đè đó! Để làm gì á? Đủ thứ trên đời: Lưu config của ứng dụng. Ghi log lỗi, log hoạt động của hệ thống. Tạo file cache để tăng tốc độ. Xuất báo cáo, invoice dưới dạng file text, JSON, CSV... Lưu trữ dữ liệu đơn giản mà không cần database phức tạp. 2. Code Ví Dụ Minh Họa Rõ Ràng (Tối Giản nhưng Chuẩn Kiến Thức) Ok, lý thuyết đủ rồi, giờ mình đi vào thực hành "thư ký" này làm việc nhé. Cú pháp cơ bản: fs.writeFile(path, data, [options], callback) hoặc dùng Promise (async/await) cho xịn. Ví dụ 1: Ghi file đơn giản với Callback (kiểu cũ nhưng vẫn dùng được): const fs = require('fs'); const tenFile = 'thong_diep_cua_creyt.txt'; const noiDung = 'Chào các bạn Gen Z! Đây là thông điệp bí mật từ Creyt. Học Node.js vui vẻ nhé!'; fs.writeFile(tenFile, noiDung, (err) => { if (err) { console.error('Ối giời ơi, có lỗi rồi Creyt ơi:', err); return; } console.log(`Đã ghi thành công vào file: ${tenFile}`); }); Ví dụ 2: Ghi file với Promise/Async-Await (chuẩn Gen Z, hiện đại hơn): const fs = require('fs').promises; // Dùng phiên bản promise của fs async function ghiThongDiepMoi() { const tenFile = 'thong_diep_moi_cua_creyt.json'; const duLieuJSON = { tacGia: 'Creyt', tieuDe: 'Hướng dẫn fs.writeFile()', noiDung: 'Node.js thật bá đạo!', version: '1.0.0' }; try { await fs.writeFile(tenFile, JSON.stringify(duLieuJSON, null, 2), 'utf8'); console.log(`Đã ghi thành công file JSON: ${tenFile}`); } catch (err) { console.error('Lỗi khi ghi file JSON:', err); } } ghiThongDiepMoi(); Giải thích nhẹ: JSON.stringify(duLieuJSON, null, 2): Cái này để biến object JavaScript thành chuỗi JSON. null, 2 là để format cho dễ đọc, mỗi cấp thụt vào 2 khoảng trắng. 'utf8': Là kiểu mã hóa, hầu như luôn dùng cái này cho tiếng Việt và các ký tự đặc biệt. 3. Vài Mẹo Hay Của Creyt (Best Practices) Để Ghi Nhớ và Dùng Thực Tế Luôn Luôn Xử Lý Lỗi (Error Handling): Đây là điều tiên quyết! Giống như lái xe phải thắt dây an toàn vậy. Mấy đứa luôn phải kiểm tra err trong callback hoặc dùng try...catch với async/await. Nếu không, ứng dụng có thể "chết lâm sàng" mà mấy đứa không biết tại sao. Hiểu Rõ Tính Bất Đồng Bộ (Asynchronous Nature): fs.writeFile() là hàm bất đồng bộ. Tức là nó sẽ "giao việc" cho hệ điều hành rồi đi làm việc khác ngay, không chờ đợi. Khi nào ghi xong hoặc có lỗi thì nó mới gọi lại callback hoặc resolve/reject Promise. Đừng bao giờ nghĩ nó chạy xong rồi mới chạy dòng code tiếp theo nhé! writeFile vs appendFile: Nhớ cái vụ "ghi đè" ban nãy không? fs.writeFile() là ghi đè toàn bộ. Nếu mấy đứa chỉ muốn thêm nội dung vào cuối file mà không mất dữ liệu cũ, hãy dùng fs.appendFile(). Giống như viết thêm vào cuối nhật ký thay vì xé trang cũ viết lại vậy. Encoding: Mặc định là utf8, rất tốt cho tiếng Việt. Nếu mấy đứa làm việc với các hệ thống cũ hoặc file đặc thù, có thể cần chỉ định encoding khác (ví dụ: 'latin1'). Quyền Ghi File (Permissions): Đôi khi, Node.js không có quyền ghi vào một thư mục nào đó. Lúc đó, fs.writeFile() sẽ báo lỗi EACCES (Permission denied). Hãy kiểm tra lại quyền của thư mục mà mấy đứa đang cố gắng ghi file vào. 4. Học Thuật Sâu Của Anh Creyt: "Thư Ký" Làm Việc Thế Nào? Mấy đứa có bao giờ tự hỏi, tại sao Node.js lại nhanh đến vậy không? Một phần là nhờ vào cái "bất đồng bộ" mà anh vừa nói đấy. Khi mấy đứa gọi fs.writeFile(), Node.js không tự mình đi ghi file đâu. Nó sẽ "ủy quyền" việc này cho hệ điều hành (OS) thông qua một cái gọi là thread pool (một nhóm các "công nhân" chuyên làm việc nặng). Cái thread pool này sẽ thực hiện việc ghi file lên ổ đĩa. Trong lúc đó, Node.js (cái "luồng chính" hay còn gọi là Event Loop) vẫn rảnh rang xử lý các yêu cầu khác, ví dụ như nhận request từ người dùng, tính toán... Khi hệ điều hành ghi file xong (thành công hay thất bại), nó sẽ báo lại cho Node.js, và Node.js sẽ kích hoạt callback hoặc xử lý Promise. Chính cơ chế này giúp ứng dụng Node.js của mấy đứa không bị "đứng hình" (blocking) khi phải chờ đợi các thao tác I/O (Input/Output) chậm chạp như ghi/đọc file hay gọi database. Nghe có vẻ phức tạp nhưng hiểu được nó, mấy đứa sẽ thấy Node.js cực kỳ mạnh mẽ! 5. Ví Dụ Thực Tế Các Ứng Dụng/Website Đã Ứng Dụng Hệ thống Log: Hầu hết các ứng dụng backend, từ app nhỏ đến hệ thống lớn, đều dùng fs.writeFile() (hoặc các thư viện dựa trên nó) để ghi lại nhật ký hoạt động, lỗi, cảnh báo vào các file log. Ví dụ: access.log, error.log. Cache Dữ Liệu: Một số trang web hoặc API server dùng fs.writeFile() để lưu trữ các phản hồi API thường xuyên được truy cập vào file tạm thời. Lần sau có yêu cầu tương tự, chỉ cần đọc file cache ra trả về, không cần gọi database, giúp tăng tốc độ "thần chưởng". Xuất Báo Cáo/Dữ Liệu: Khi mấy đứa nhấn nút "Export to CSV" hay "Download Report" trên các dashboard quản lý, rất có thể backend đã dùng fs.writeFile() để tạo ra file đó rồi gửi về cho mấy đứa. Cấu hình Ứng Dụng: Các file cấu hình như .env, config.json đôi khi được tạo hoặc cập nhật tự động bởi các script Node.js dùng fs.writeFile(). 6. Thử Nghiệm Đã Từng và Hướng Dẫn Nên Dùng Cho Case Nào Creyt đã từng thử nghiệm: Hồi xưa, anh từng làm một cái "hệ thống" nhỏ tự động crawl dữ liệu từ vài trang web, sau đó dùng fs.writeFile() để lưu trữ từng mẩu tin vào các file JSON riêng biệt. Sau đó thì có một script khác đọc các file JSON đó lên để xử lý. Nó chạy ngon lành cho dữ liệu nhỏ và vừa. Nên dùng cho: Ghi log: Tuyệt vời để ghi nhật ký, thông báo lỗi. Lưu trữ cấu hình: Các file cấu hình nhỏ, ít thay đổi. Tạo file tạm thời: Cache, báo cáo, file xuất dữ liệu một lần. Lưu trữ dữ liệu nhỏ, đơn giản: Ví dụ, lưu thông tin điểm số của một game offline đơn giản, lưu danh sách việc cần làm (todo list) của một ứng dụng desktop. KHÔNG nên dùng cho: Database chính thức: Đừng bao giờ nghĩ fs.writeFile() có thể thay thế một database chuyên nghiệp như MySQL, PostgreSQL, MongoDB nhé. Khi dữ liệu lớn, cần truy vấn phức tạp, quan hệ, bảo mật, tính toàn vẹn, đa người dùng truy cập cùng lúc, thì file system không đủ sức đâu. Ghi file liên tục, tốc độ cao với nhiều luồng: Nếu có hàng trăm, hàng nghìn yêu cầu ghi file cùng lúc, việc quản lý race condition (khi nhiều tác vụ cố gắng ghi vào cùng một file) sẽ rất phức tạp và dễ gây lỗi, hỏng dữ liệu. Lúc đó cần các giải pháp queuing hoặc database chuyên dụng. Thấy không, fs.writeFile() tuy đơn giản nhưng lại là một "thư ký" cực kỳ đắc lực trong Node.js, giúp mấy đứa Gen Z lưu trữ và quản lý dữ liệu một cách hiệu quả. Nắm vững nó, mấy đứa sẽ có thêm một công cụ mạnh mẽ trong bộ đồ nghề lập trình của mình đấy! Chúc mấy đứa code vui vẻ! 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é!

47 Đọc tiếp