记录一些Node.js应用中的小知识点。如果你谷歌/百度“Node.js如何判断一个文件是否存在”,发现给出的很多答案还在使用fs.exists,这里不推荐使用fs.exists,可以选择fs.stat或者fs.access。为什么不推荐fs.exists我们在设计回调函数的时候,通常会遵循一个“错误优先的回调函数”的原则,即返回值的第一个参数是错误信息,用来验证是否有错误,其他参数用于返回数据。下面是fs.exists的使用示例,直接返回一个布尔值,违反了“错误优先回调函数”的设计原则。这是原因之一。fs.exists('/etc/passwd',(exists)=>{console.log(exists?'exists':'doesn'texist');});另一种是fs.open()中不推荐的,fs.在readFile()或fs.writeFile()之前使用fs.exists()来确定文件是否存在,因为这会导致竞争条件。如果是多进程下,程序的执行并不是完全线性的。当程序的一个进程执行fs.exists和fs.writeFile()时,其他进程可能会改变它们之间文件的状态,这会导致一些意想不到的结果。不推荐:(async()=>{constexists=awaitutil.promisify(fs.exists)('text.txt');console.log(exists);awaitsleep(10000);if(exists){try{constres=awaitutil.promisify(fs.readFile)('text.txt',{encoding:'utf-8'});console.log(res);}catch(err){console.error(err.code,err.message);投掷者;}}})();推荐:(async()=>{try{constdata=awaitutil.promisify(fs.readFile)('text.txt',{encoding:'utf-8'});console.log(data);}catch(err){if(err.code==='ENOENT'){console.error('Filedoesnotexists');}else{throwerr;}}})();目前fs.exists已被弃用。另外需要明确的是,只有在不直接使用文件的时候才会检查文件是否存在。下面推荐几种检查文件是否存在的方法。使用fs.statfs.stat返回一个fs.Stats对象,提供了很多关于文件的信息,比如文件大小,创建时间等,有两个方法stats.isDirectory()和stats.isFile()判断是否它是一个目录或文件。conststats=awaitutil.promisify(fs.stat)('text1.txt');console.log(stats.isDirectory());//falseconsole.log(stats.isFile());//true如果只是检查是否文件存在,推荐使用下面的fs.access。使用fs.accessfs.access接收一个mode参数判断文件是否存在,是否可读,可写,返回值为err参数。constfile='text.txt';//检查文件是否存在于当前目录。fs.access(file,fs.constants.F_OK,(err)=>{console.log(`${file}${err?'不存在':'存在'}`);});//检查文件是否可读。fs.access(file,fs.constants.R_OK,(err)=>{console.log(`${file}${err?'unreadable':'readable'}`);});//检查是否文件是可写的。fs.access(file,fs.constants.W_OK,(err)=>{console.log(`${file}${err?'无法写入':'writable'}`);});//检查文件是否存在于当前目录并且可写。fs.access(file,fs.constants.F_OK|fs.constants.W_OK,(err)=>{if(err){console.error(`${file}${err.code==='ENOENT'?'不存在':'只能读取'}`);}else{console.log(`${file}存在并且可以写入`);}});同样不推荐在fs.open()中,在fs.readFile()或fs.writeFile()之前使用fs.exists()判断文件是否存在会导致racecondition。参考http://nodejs.cn/api/fs.html
