我正在编写一个函数createFile
,用于在一个目录中创建一个文件,除非该文件已经存在。我使用Node.js原生fs
包来执行所有文件操作。我想让我的函数异步,所以我把所有的fs
函数都包装在promises中:
function writeFilePromise(writePath, textContent) {
return new Promise((resolve, reject) => {
fs.writeFile(writePath, textContent, (err) => {
reject();
});
resolve();
});
}
function mkDirPromise(dir) {
return new Promise(((resolve, reject) => {
fs.mkdir(path.join(constants.FILES_STORAGE_DIR, dir), (err) => {
reject(err);
});
resolve();
}));
}
然后我还想在promise中包装fs.existsSync
,以完成我的功能,但包装它偶尔会导致不正确的行为,也就是说,如果文件的目录不存在,而我想创建一个目录,则创建的目录将是空的,而不会创建文件。通过调试,我发现只有同步fs.existsSync
才能工作,并且始终是。这是函数代码:
function createFile(dir, fileName, httpMethod, textContent) {
return new Promise(((resolve, reject) => {
const searchPath = path.join(ROOT_DIR, dir, fileName);
if (httpMethod === POST && fs.existsSync(searchPath)) {
reject();
} else {
const fileExistsStatus = fs.existsSync(path.join(ROOT_DIR, dir));
(async function fsOperations() {
try {
if (!fileExistsStatus) {
await mkDirPromise(dir);
}
await writeFilePromise(searchPath, textContent);
resolve();
} catch (err) {
reject(err);
}
}());
}
}));
}
我遗漏了什么?我怎样才能把我的函数变成真正的异步函数?
发布于 2018-06-09 04:53:37
首先,您构造了writeFilePromise
和mkDirPromise
,以便它们始终是resolve
,而不是reject
。因为fs.writeFile
和fs.mkdir
是异步的,所以一旦它们启动,线程就会立即转移到resolve()
。我想你的意思是..。
function writeFilePromise(writePath, textContent) {
return new Promise((resolve, reject) => {
fs.writeFile(writePath, textContent, (err) => {
if (err) reject();
else resolve();
});
});
}
function mkDirPromise(dir) {
return new Promise((resolve, reject) => {
fs.mkdir(path.join(constants.FILES_STORAGE_DIR, dir), (err) => {
if (err) reject();
else resolve();
});
});
}
就fs.exists
而言,它已经过时了,所以我不推荐使用它。相反,可以尝试使用fs.access
function accessPromise(dir) {
return new Promise((resolve, reject) => {
fs.access(dir, (err) => {
if (err) reject();
else resolve();
});
});
}
最后,尝试调整使用async
函数声明的位置,以确保正确地同步代码:
async function createFile(dir, fileName, httpMethod, textContent) {
const searchPath = path.join(ROOT_DIR, dir, fileName);
if (httpMethod === POST && await accessPromise(searchPath)) {
return false;
} else {
const fileExistsStatus = await accessPromise(path.join(ROOT_DIR, dir));
try {
if (!fileExistsStatus) {
await mkDirPromise(dir);
}
await writeFilePromise(searchPath, textContent);
return true;
} catch (err) {
return false;
}
}
}
记得在调用该函数时使用await createFile(dir, fileName, httpMethod, textContent)
。
发布于 2018-06-09 04:56:18
首先,考虑用有意义的东西来拒绝,而不仅仅是reject()
由于您考虑的是async和promise,我不推荐使用fs.xxxSync()
函数。另外,fs.exists
已被弃用,请尝试使用fs.stat()
。
我猜只有在HTTP方法是POST的情况下才会创建文件,但是在当前的if-else逻辑中,当HTTP方法不是POST时,总是会创建文件。
不需要创建立即调用的异步函数。
试试这个:
function createFile(dir, fileName, httpMethod, textContent) {
return new Promise((resolve, reject) => {
const searchPath = path.join(ROOT_DIR, dir, fileName);
if (httpMethod !== POST) {
return reject(new Error('Invalid HTTP method'));
}
fs.exists(searchPath, (exists) => {
if (exists) {
return reject(new Error('Already exists'));
}
fs.exists(path.join(ROOT_DIR, dir), async (exists) => {
try {
if (!exists) {
await mkDirPromise(dir);
}
await writeFilePromise(searchPath, textContent);
resolve();
} catch (err) {
reject(err);
}
});
});
});
}
https://stackoverflow.com/questions/50767829
复制相似问题