如果目录不存在,这是创建目录的正确方法吗?它应该对该脚本具有完全的权限,并且可以被其他人读取。
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
var fs = require('fs');
var dir = './tmp';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
不,出于多种原因。
该文档明确阻止您使用exists
。
fs.exists()
是过时的,仅出于历史原因存在。几乎永远没有理由在自己的代码中使用它。特别是,在打开文件之前检查文件是否存在是一种反模式,使您容易受到竞争状况的影响:另一个过程可能会在调用
fs.exists()
和fs.open()
之间删除该文件。只需打开文件,然后在不存在时处理错误即可。
由于我们在谈论目录而不是文件,因此此建议意味着您应该无条件调用mkdir
并忽略EEXIST
。
通常,应避免使用 * Sync
方法。它们正在阻塞,这意味着在您访问磁盘时,程序中绝对不会发生任何其他事情。这是一个非常昂贵的操作,花费的时间打破了节点事件循环的核心假设。
* Sync
方法通常在单一用途的快速脚本(先执行一件事然后退出的脚本)中很好用,但是在编写服务器时几乎永远不要使用:服务器将无法在整个过程中对任何人做出响应 I / O 请求的持续时间。如果多个客户端请求需要 I / O 操作,则服务器将很快停止运行。
我唯一考虑在服务器应用程序中Sync
方法的操作是在启动时发生一次(且仅一次)的操作。例如, require
实际上使用readFileSync
加载模块。
即使那样,您仍然必须小心,因为大量同步 I / O 可能会不必要地减慢服务器的启动时间。
相反,您应该使用异步 I / O 方法。
因此,如果我们将这些建议汇总在一起,我们将得到如下结果:
function ensureExists(path, mask, cb) {
if (typeof mask == 'function') { // allow the `mask` parameter to be optional
cb = mask;
mask = 0777;
}
fs.mkdir(path, mask, function(err) {
if (err) {
if (err.code == 'EEXIST') cb(null); // ignore the error if the folder already exists
else cb(err); // something else went wrong
} else cb(null); // successfully created folder
});
}
我们可以这样使用它:
ensureExists(__dirname + '/upload', 0744, function(err) {
if (err) // handle folder creation error
else // we're all good
});
当然,这并不能解决诸如以下的极端情况
mkdir
方法可以递归地在路径中创建任何目录,而忽略存在的目录。
// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
if (err) throw err;
});
注意:您需要首先导入内置的fs
模块。
现在,这是一个更强大的示例,该示例利用本机 ES 模块(启用了标志并具有. mjs 扩展名),处理了非根路径,并说明了完整的路径名:
import fs from 'fs';
import path from 'path';
createDirectories(pathname) {
const __dirname = path.resolve();
pathname = pathname.replace(/^\.*\/|\/?[^\/]+\.[a-z]+|\/$/g, ''); // Remove leading directory markers, and remove ending /file-name.extension
fs.mkdir(path.resolve(__dirname, pathname), { recursive: true }, e => {
if (e) {
console.error(e);
} else {
console.log('Success');
}
});
}
您可以像createDirectories('/components/widget/widget.js');
。
当然,您可能希望通过将诺言与 async / await 结合使用来在创建目录时以更具可读性的同步外观方式利用文件创建来获得更多的希望;但是,这超出了问题的范围。