并发控制
- 使用
async/await
结合Promise.all
:将多个异步操作封装为Promise,然后使用Promise.all
并行执行这些Promise。例如,在处理多个文件读取操作时:
const fs = require('fs').promises;
async function readFiles() {
const files = ['file1.txt', 'file2.txt', 'file3.txt'];
const promises = files.map(file => fs.readFile(file, 'utf8'));
const results = await Promise.all(promises);
return results;
}
- 限制并发数:当有大量异步任务时,过多的并发可能导致资源耗尽。可以使用
async - queue
这样的库来限制并发数量。例如:
const Queue = require('async - queue');
const fs = require('fs').promises;
const queue = new Queue(async function (file, callback) {
try {
const data = await fs.readFile(file, 'utf8');
callback(null, data);
} catch (err) {
callback(err);
}
}, 5); // 最大并发数为5
const files = ['file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', 'file5.txt', 'file6.txt'];
files.forEach(file => queue.push(file));
queue.drain(() => {
console.log('所有任务完成');
});
流处理
- 文件读取流:对于大文件读取,使用
fs.createReadStream
。例如:
const fs = require('fs');
const readableStream = fs.createReadStream('largeFile.txt', { encoding: 'utf8' });
readableStream.on('data', (chunk) => {
// 处理读取到的数据块
console.log('读取到数据块:', chunk.length);
});
readableStream.on('end', () => {
console.log('文件读取完成');
});
- 管道流:可以将读取流直接通过管道连接到写入流,实现高效的数据传输。例如,将一个文件内容复制到另一个文件:
const fs = require('fs');
const readableStream = fs.createReadStream('sourceFile.txt');
const writableStream = fs.createWriteStream('destinationFile.txt');
readableStream.pipe(writableStream);
优化回调
- 避免回调地狱:深度嵌套的回调函数会使代码难以维护。可以通过将回调函数提取为独立的函数来改善。例如:
const fs = require('fs');
function readFileCallback(file, callback) {
fs.readFile(file, 'utf8', callback);
}
function processFileData(err, data) {
if (err) {
console.error(err);
return;
}
console.log('文件内容:', data);
}
readFileCallback('example.txt', processFileData);
Promise的使用
- 将回调函数转换为Promise:Node.js中许多异步API使用回调,使用
util.promisify
可以将其转换为Promise。例如:
const util = require('util');
const fs = require('fs');
const readFilePromise = util.promisify(fs.readFile);
async function readFile() {
try {
const data = await readFilePromise('example.txt', 'utf8');
console.log('文件内容:', data);
} catch (err) {
console.error(err);
}
}
readFile();
- 合理处理Promise链:在Promise链中,每个
.then
方法返回新的Promise,确保错误能够正确传递和处理。例如:
const fs = require('fs').promises;
fs.readFile('file1.txt', 'utf8')
.then(data => {
// 处理文件1的数据
console.log('文件1内容:', data);
return fs.readFile('file2.txt', 'utf8');
})
.then(data => {
// 处理文件2的数据
console.log('文件2内容:', data);
})
.catch(err => {
console.error('读取文件出错:', err);
});