异步文件读取,无法使函数在返回前完成
Asynchronous file reading, cannot make function finish before returning
我正在尝试读取文件夹中的所有文件,检查它是否有 featured: true
道具,如果有则增加计数器,如果有超过 1 个这样的文件则抛出错误。但出于某种原因,我的代码没有等待,直接跳转到最后一部分,这是输出
this should be last
Inside item, looking for featured prop
Inside item, looking for featured prop
我的代码:
const fs = require('fs');
const findInDir = require('./utils/findInDir');
(async () => {
const dir = './public/page-data/blog';
const fileRegex = /.*/;
const allFiles = findInDir(dir, fileRegex);
let result = 0;
await allFiles.map(file => {
fs.readFile(file, 'utf8', (err, data) => {
const obj = JSON.parse(data);
if (obj.result.pageContext.featured === true) {
console.log('Inside item, looking for featured prop');
result += 1;
}
});
});
console.log('this should be last');
if (result > 1) {
throw new Error('There are multiple featured blog posts, please fix.');
}
})();
需要一些帮助来理解我做错了什么。
您需要使用 fs.readFile
的非回调版本才能真正 await
读取文件。使用 .map
也没有多大意义,因为您实际上并没有映射某些东西,所以只需使用 for .. of
循环:
for (const file of allFiles){
try {
const data = await fs.promises.readFile(file);
// ...
} catch(err) {
// handle error
}
}
console.log('this should be last');
快速解决方案:
(async () => {
const dir = "./public/page-data/blog";
const fileRegex = /.*/;
const allFiles = findInDir(dir, fileRegex);
try {
await Promise.all(
allFiles.map((file) => {
return new Promise((resolve, reject) => {
fs.readFile(file, "utf8", (err, data) => {
const obj = JSON.parse(data);
if (obj.result.pageContext.featured === true) {
reject("Inside item, looking for featured prop");
} else {
resolve();
}
});
});
})
);
} catch (err) {
throw new Error("There are multiple featured blog posts, please fix.");
}
})();
我不是像在循环中那样逐一检查每一项,而是这样做的。如果其中任何一个 featured
设置为真,它会检查“平行”。因此它比循环更快
如果它 true
我拒绝它并且 Promise.all()
停止。 Promise.all()
的 try / catch
捕获拒绝
您只需要了解一件事就可以知道何时使用 await
何时不使用。
只有在承诺上使用 await
才有意义。
你怎么知道它是否是一个承诺?就console.log
吧
它是否控制台日志 Promise
?使用 await
它不是控制台日志 Promise
吗?使用 await
没有意义
这 return 只是一个数组。使用 await
有意义吗?不,它不 return Promise
但是如果你这样做:
你有一系列的承诺。
这里有点不同。你有一个数组,但里面的元素是一个承诺。
您可以使用 Promise.all()
它基本上等待数组中的每个项目直到完成。
我正在尝试读取文件夹中的所有文件,检查它是否有 featured: true
道具,如果有则增加计数器,如果有超过 1 个这样的文件则抛出错误。但出于某种原因,我的代码没有等待,直接跳转到最后一部分,这是输出
this should be last
Inside item, looking for featured prop
Inside item, looking for featured prop
我的代码:
const fs = require('fs');
const findInDir = require('./utils/findInDir');
(async () => {
const dir = './public/page-data/blog';
const fileRegex = /.*/;
const allFiles = findInDir(dir, fileRegex);
let result = 0;
await allFiles.map(file => {
fs.readFile(file, 'utf8', (err, data) => {
const obj = JSON.parse(data);
if (obj.result.pageContext.featured === true) {
console.log('Inside item, looking for featured prop');
result += 1;
}
});
});
console.log('this should be last');
if (result > 1) {
throw new Error('There are multiple featured blog posts, please fix.');
}
})();
需要一些帮助来理解我做错了什么。
您需要使用 fs.readFile
的非回调版本才能真正 await
读取文件。使用 .map
也没有多大意义,因为您实际上并没有映射某些东西,所以只需使用 for .. of
循环:
for (const file of allFiles){
try {
const data = await fs.promises.readFile(file);
// ...
} catch(err) {
// handle error
}
}
console.log('this should be last');
快速解决方案:
(async () => {
const dir = "./public/page-data/blog";
const fileRegex = /.*/;
const allFiles = findInDir(dir, fileRegex);
try {
await Promise.all(
allFiles.map((file) => {
return new Promise((resolve, reject) => {
fs.readFile(file, "utf8", (err, data) => {
const obj = JSON.parse(data);
if (obj.result.pageContext.featured === true) {
reject("Inside item, looking for featured prop");
} else {
resolve();
}
});
});
})
);
} catch (err) {
throw new Error("There are multiple featured blog posts, please fix.");
}
})();
我不是像在循环中那样逐一检查每一项,而是这样做的。如果其中任何一个 featured
设置为真,它会检查“平行”。因此它比循环更快
如果它 true
我拒绝它并且 Promise.all()
停止。 Promise.all()
的 try / catch
捕获拒绝
您只需要了解一件事就可以知道何时使用 await
何时不使用。
只有在承诺上使用 await
才有意义。
你怎么知道它是否是一个承诺?就console.log
吧
它是否控制台日志 Promise
?使用 await
它不是控制台日志 Promise
吗?使用 await
这 return 只是一个数组。使用 await
有意义吗?不,它不 return Promise
但是如果你这样做:
你有一系列的承诺。
这里有点不同。你有一个数组,但里面的元素是一个承诺。
您可以使用 Promise.all()
它基本上等待数组中的每个项目直到完成。