为什么异步函数中的等待不适用于 fs 模块?
Why await within async function doesn't work for fs modules?
我正在尝试通过我的 js 代码读取 sample.json 文件。首先,我的程序检查指定路径中每个文件夹中的 sample.json。如果可用,它会读取 sample.json 并获取数据。但是使用的 await 没有按预期工作,只是在异步函数完成执行之前将空对象传递给调用函数。我已附上该问题的图片。
async function getAvailableJson(filesPath) {
let detectedJson = {};
let folders = await fs.promises.readdir(filesPath);
folders.forEach(async function(folder) {
await fs.promises.access(path.join(filesPath, folder, "Sample.json")).then(async function() {
jsonData = await fs.promises.readFile(path.join(filesPath, folder ,"Sample.json"))
const directory = JSON.parse(jsonData)
const hashvalue = Hash.MD5(jsonData)
detectedJson[directory["dirName"]] = {
name: directory["dirName"],
version: directory["dirVersion"],
hash: hashvalue
}
console.log(detectedJson);
}).catch(function(err) {
if(err.code === "ENOENT")
{}
});
});
return detectedJson;
}
我不想使用任何同步功能,因为它会创建不必要的锁。我也尝试过 fs.readdir、fs.access 和 fs.readFile 函数。有人可以指出我在这里做错了什么吗,因为我是 Node.js 的新手,在此先感谢。
Sample Image
将您的 .forEach()
更改为使用 for/of
并且通常通过不混合 await
和 .then()
来简化。
async function getAvailableJson(filesPath) {
let detectedJson = {};
let folders = await fs.promises.readdir(filesPath);
let detectedJson = {};
for (let folder of folders) {
let file = path.join(filesPath, folder, "Sample.json");
try {
let jsonData = await fs.promises.readFile(file);
const directory = JSON.parse(jsonData);
const hashvalue = Hash.MD5(jsonData);
detectedJson[directory["dirName"]] = {
name: directory["dirName"],
version: directory["dirVersion"],
hash: hashvalue
};
} catch (err) {
// silently skip any directories that don't have sample.json in them
// otherwise, throw the error to stop further processing
if (err.code !== "ENOENT") {
console.log(`Error on file ${file}`, err);
throw err;
}
}
console.log(detectedJson);
}
return detectedJson;
}
变更摘要:
- 将
.forEach()
替换为for/of
。
- 删除
.then()
并仅使用 await
。
- 删除
.catch()
并仅使用 try/catch
。
- 删除对
fs.promises.access()
的调用,因为错误只能在 fs.promises.readFile()
上处理
- 如果错误不是 ENOENT,请添加日志记录,这样您就可以看到错误是什么以及它在哪个文件中。你几乎不想在没有日志记录的情况下默默地吃掉一个错误。尽管您可能希望跳过某些特定错误,但必须记录其他错误。重新抛出非 ENOENT 的错误,以便调用者看到它们。
- 将此处使用的所有变量声明并初始化为局部变量。
.forEach()
不是 promise-aware,所以在里面使用 await
根本不会暂停外部函数。相反,使用 for/of
循环,它不会创建额外的函数作用域,并允许 await
暂停父函数。
此外,我认为 .forEach()
如今已经过时了。它不是承诺意识的。 for/of
是一种更高效、更通用的迭代方式。而且,不再需要使用 .forEach()
回调创建新的函数作用域,因为我们有 let
和 const
的块作用域变量。我不再使用它了。
此外,我看不出您为什么要使用 fs.promises.access()
进行预检。这只会造成竞争条件,您也可以只处理从 fs.promises.readFile()
得到的任何错误,因为在没有竞争条件的情况下,它会做同样的事情。
另请参阅关于类似问题的 。
我正在尝试通过我的 js 代码读取 sample.json 文件。首先,我的程序检查指定路径中每个文件夹中的 sample.json。如果可用,它会读取 sample.json 并获取数据。但是使用的 await 没有按预期工作,只是在异步函数完成执行之前将空对象传递给调用函数。我已附上该问题的图片。
async function getAvailableJson(filesPath) {
let detectedJson = {};
let folders = await fs.promises.readdir(filesPath);
folders.forEach(async function(folder) {
await fs.promises.access(path.join(filesPath, folder, "Sample.json")).then(async function() {
jsonData = await fs.promises.readFile(path.join(filesPath, folder ,"Sample.json"))
const directory = JSON.parse(jsonData)
const hashvalue = Hash.MD5(jsonData)
detectedJson[directory["dirName"]] = {
name: directory["dirName"],
version: directory["dirVersion"],
hash: hashvalue
}
console.log(detectedJson);
}).catch(function(err) {
if(err.code === "ENOENT")
{}
});
});
return detectedJson;
}
我不想使用任何同步功能,因为它会创建不必要的锁。我也尝试过 fs.readdir、fs.access 和 fs.readFile 函数。有人可以指出我在这里做错了什么吗,因为我是 Node.js 的新手,在此先感谢。
Sample Image
将您的 .forEach()
更改为使用 for/of
并且通常通过不混合 await
和 .then()
来简化。
async function getAvailableJson(filesPath) {
let detectedJson = {};
let folders = await fs.promises.readdir(filesPath);
let detectedJson = {};
for (let folder of folders) {
let file = path.join(filesPath, folder, "Sample.json");
try {
let jsonData = await fs.promises.readFile(file);
const directory = JSON.parse(jsonData);
const hashvalue = Hash.MD5(jsonData);
detectedJson[directory["dirName"]] = {
name: directory["dirName"],
version: directory["dirVersion"],
hash: hashvalue
};
} catch (err) {
// silently skip any directories that don't have sample.json in them
// otherwise, throw the error to stop further processing
if (err.code !== "ENOENT") {
console.log(`Error on file ${file}`, err);
throw err;
}
}
console.log(detectedJson);
}
return detectedJson;
}
变更摘要:
- 将
.forEach()
替换为for/of
。 - 删除
.then()
并仅使用await
。 - 删除
.catch()
并仅使用try/catch
。 - 删除对
fs.promises.access()
的调用,因为错误只能在fs.promises.readFile()
上处理
- 如果错误不是 ENOENT,请添加日志记录,这样您就可以看到错误是什么以及它在哪个文件中。你几乎不想在没有日志记录的情况下默默地吃掉一个错误。尽管您可能希望跳过某些特定错误,但必须记录其他错误。重新抛出非 ENOENT 的错误,以便调用者看到它们。
- 将此处使用的所有变量声明并初始化为局部变量。
.forEach()
不是 promise-aware,所以在里面使用 await
根本不会暂停外部函数。相反,使用 for/of
循环,它不会创建额外的函数作用域,并允许 await
暂停父函数。
此外,我认为 .forEach()
如今已经过时了。它不是承诺意识的。 for/of
是一种更高效、更通用的迭代方式。而且,不再需要使用 .forEach()
回调创建新的函数作用域,因为我们有 let
和 const
的块作用域变量。我不再使用它了。
此外,我看不出您为什么要使用 fs.promises.access()
进行预检。这只会造成竞争条件,您也可以只处理从 fs.promises.readFile()
得到的任何错误,因为在没有竞争条件的情况下,它会做同样的事情。
另请参阅关于类似问题的