条件异步回调

时间:2018-04-08 20:57:45

标签: javascript node.js callback

我正在编写一个电子程序,它将CSV文件作为输入,并根据CSV内容和文件存在进行文件操作(这是为了管理MAME街机)。

为了在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,然后在每次文件复制之后,它发现它为零并触发回调。

如何在所有这些嵌套回调和条件结束时可靠地触发回调?

由于

1 个答案:

答案 0 :(得分:1)

我试图更改代码而不会大量覆盖您的样式 - 假设有理由避免像async,async / await&amp;本机Promises和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(); } }}) }); }); lib。

在处理行之后,您需要递减行。我将处理逻辑拉出到一个函数中以使其更清晰:

$(seq)