一. 在之前的node版本中读写文件可以通过fs模块的readFile() 和 readFileSync()方法。其中,readFile()为异步读取,readFileSync()为同步读取。
- sync 同步
- async 异步
下面举例说明两种操作
先结论:异步读取文件的时候由操作系统在后台进行读取,不会阻碍下面的代码执行。同步读取的时候会阻碍下面的代码执行。
test.js
var fs = require('fs'); //获取fs模块
console.log('start async read'); //异步读取开始
fs.readFile('test2.js',function(error,date){ //读取文件,回调函数第一个参数表示错误信息,第二个参数为读取的文本内容
if(error){
console.log(error);
}else{
console.log('end async read'); //异步读取结束
}
});
console.log('start sync read'); //同步读取开始
var date = fs.readFileSync('log.txt','utf-8');
console.log('end sync read'); //同步读取结束
结果:
看出是按这个顺序执行的:异步读取开始--------------->同步读取开始--------------------->同步读取结束---------------->异步读取结束
异步读取没有结束,同步读取就完成了。
结论:异步读取没有阻塞下面代码的执行。
调换一下代码就更明显了
var fs = require('fs'); //获取fs模块
console.log('start sync read'); //同步读取开始
var date = fs.readFileSync('log.txt','utf-8');
console.log('end sync read'); //同步读取结束
console.log('start async read'); //异步读取开始
fs.readFile('test2.js',function(error,date){ //读取文件,回调函数第一个参数表示错误信息,第二个参数为读取的文本内容
if(error){
console.log(error);
}else{
console.log('end async read'); //异步读取结束
}
});
看出是按这个顺序执行的:同步读取开始--------->同步读取结束-------->异步读取开始------->异步读取结束
结论:同步读取 阻塞下面代码执行。
二. 除此之外,我们还可以用fs模块里的promises里的readFile和writeFile来读写文件
在nodejs文档中,v10版本里新增了通过promise来处理异步操作读取文件的API,即fs模块里的promises的readFile()和writeFile()
const {promises: {readFile, writeFile}} = require('fs');
(async () => {
let content = await readFile('./data.txt', 'utf8');
await writeFile('2.txt', content, 'utf8');
console.log('ok');
})();
注意!!! forEach如何处理异步,请用for … of
在这段代码中,存在一个常见的 JavaScript 异步操作问题。具体来说,files.forEach
中的异步操作无法按预期方式工作。这是因为 forEach
方法无法正确处理异步函数的返回值或等待异步函数的完成。
为了解决这个问题,您可以使用 for...of
循环来遍历文件数组,并在其中使用 await
关键字来等待每个异步操作的完成。这样可以确保每个文件的内容都能被正确处理,并且可以正确地构建 Markdown 内容。
下面是修改后的代码示例:
const getMdContent = async () => {
let mdResult = ''
for (const file of files) {
try {
const dataString = await readFile(file)
// 使用 eval 解析文件内容
const moduleWrapper = new Function('module', 'exports', dataString)
const module = { exports: {} }
moduleWrapper(module, module.exports)
// 获取questions
const questions = module.exports.questions ?? []
mdResult += generateMarkdown(questions) + '\n\n'
} catch (error) {
console.error('Error parsing file content:', error)
}
}
return mdResult
}
在这个修改后的代码中,我们使用了 for...of
循环来遍历文件数组,并在其中使用 await
关键字来等待每个异步操作的完成。这样可以确保每个文件的内容都能被正确处理,并且可以正确地构建 Markdown 内容。
通过这种方式,您可以解决异步操作无法按预期方式工作的问题,确保每个文件的内容都能被正确处理。