我正在编写一个 Electron 程序,它接受 CSV 文件作为输入,并根据 CSV 内容和文件存在执行文件操作(用于管理 MAME 街机 ROM)。
为了在 UI 端有一个进度条,我将代码从完全同步(因为它更容易)切换为异步。
我只是不知道如何在处理 CSV 文件中的所有行并且复制或删除所有 zip 文件时可靠地向用户显示消息。
这是一个(简化的)示例方法:
fs.readFile(file, { 'encoding': 'utf8' }, (err, fileContents) => {
let fileCsv = csvparse(fileContents);
let lines = fileCsv.length;
fileCsv.forEach((line) => {
lines--;
let zip = line.name + '.zip';
let sourceRom = path.join(romset, zip);
let destRom = path.join(selection, zip);
this.emit('progress.add', fileCsv.length, fileCsv.length - lines, zip);
if (fs.existsSync(sourceRom) && !fs.existsSync(destRom)) {
fs.copy(sourceRom, destRom, (err) => {
let sourceChd = path.join(romset, game);
if (fs.existsSync(sourceChd)) {
fs.copy(sourceChd, path.join(selection, game), (err) => {
if (lines <= 0) { callback(); } // chd is copied
});
} else {
if (lines <= 0) { callback(); } // no chd, rom is copied
}
});
} else {
if (lines <= 0) { callback(); } // no source found or already exists
}
});
});
问题在于 CSV 文件的处理速度非常快,但文件的复制速度却不那么快。因此它将 lines
计数器递减到 0,然后在每次文件复制之后,它发现它为零并触发回调。
如何在所有这些嵌套回调和条件结束时可靠地触发回调?
谢谢
最佳答案
我尝试在不大量覆盖您的样式的情况下更改代码 - 假设有理由避免诸如 bluebird
、async/await 和 native Promises 以及 async
等内容库。
处理完一行后,您需要减少行数。我将处理逻辑提取到一个函数中以使这一点更清楚:
function processLine({
sourceRom, destRom, romset, game, callback
}) {
if (fs.existsSync(sourceRom) && !fs.existsSync(destRom)) {
fs.copy(sourceRom, destRom, (err) => {
// *really* should handle this error
let sourceChd = path.join(romset, game);
if (fs.existsSync(sourceChd)) {
fs.copy(sourceChd, path.join(selection, game), (err) => {
// *really* should handle this error
callback();
});
} else {
callback();
}
});
} else {
callback() // no source found or already exists
}
}
fs.readFile(file, { 'encoding': 'utf8' }, (err, fileContents) => {
let fileCsv = csvparse(fileContents);
let lines = fileCsv.length;
fileCsv.forEach((line) => {
let zip = line.name + '.zip';
let sourceRom = path.join(romset, zip);
let destRom = path.join(selection, zip);
this.emit('progress.add', fileCsv.length, fileCsv.length - lines, zip);
processLine({ sourceRom, destRom, game, romset, callback: () => {
lines--;
if (lines <= 0) {
callback();
}
}})
});
});
关于javascript - 有条件的异步回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49722719/