Node.js中用Chokidar+fs-extra实现文件同步遇错求解决方案
Looks like you've hit a couple of common pitfalls here—let's fix your code step by step:
1. Case-Sensitive Function Name Mismatch
First off, JavaScript is case-sensitive. You defined your function as UpdateFile() (capital U) but tried to call updateFile() (lowercase u) in the chokidar event. This is throwing a ReferenceError: updateFile is not defined—that's the first easy fix.
2. Inefficient & Error-Prone Directory Copy Logic
Right now, every time a single file changes, you're copying the entire data/2018/05 directory into data/2018/05/new. This causes two big issues:
- If the
newsubdirectory already exists, fs-extra'scopymethod will throw an error by default (it doesn't overwrite directories unless you explicitly allow it). - You're wasting resources copying every file in the directory instead of just the one that changed.
Instead, you should only copy the specific file that was modified to its corresponding path in the target directory.
3. Better Error Handling with Async/Await
Callbacks work, but async/await makes your code cleaner and error handling more straightforward. Let's refactor your code to use this pattern.
Corrected Full Code
const fs = require('fs-extra'); const chokidar = require('chokidar'); const path = require('path'); // Don't forget to require path for directory handling // Set up your watcher const watcher = chokidar.watch('data/2018/05', { ignored: /^\./, persistent: true }); // Async function to handle single file copies async function updateFile(changedFilePath) { try { // Generate the target path by mirroring the file structure in the 'new' subdirectory const targetFilePath = changedFilePath.replace('data/2018/05', 'data/2018/05/new'); // Make sure the target directory exists (creates it if not) await fs.ensureDir(path.dirname(targetFilePath)); // Copy the modified file, allowing overwrite of existing files await fs.copy(changedFilePath, targetFilePath, { overwrite: true }); console.log(`Successfully updated: ${changedFilePath} → ${targetFilePath}`); } catch (err) { // Log detailed error info to debug easier console.error(`Failed to update file: ${err.message}`, err); } } // Listen for file changes watcher.on('change', async (filePath) => { console.log(`CHANGE DETECTED: ${filePath}`); // Call our fixed copy function with the actual changed file path await updateFile(filePath); });
Key Improvements Explained
- Fixed function name: We're using
updateFile()consistently (lowercase start, matching the call). - Targeted file copy: Only the modified file gets copied, not the entire directory.
- Directory safety:
fs.ensureDir()creates any missing parent directories for the target file, so you don't get "no such file or directory" errors. - Overwrite permission: The
{ overwrite: true }option lets you replace existing files in the target directory, which is usually what you want for syncing. - Clear error logs: The try/catch block captures and prints detailed errors, making it easy to debug issues like permission problems or invalid paths.
If you actually need to sync the entire directory (not just individual changed files), you could look into fs-extra's sync method, but for most change-event use cases, targeting individual files is more efficient.
内容的提问来源于stack exchange,提问作者Sarotobi

