javascript - 有条件的异步回调

标签 javascript node.js callback

我正在编写一个 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/

相关文章:

jquery - 使用 Jade 和 Bootstrap 在 Node.js 上进行标签和自动完成

javascript - 了解 javascript 中的回调和闭包

node.js - Nodejs/Express POST 请求中间件无法在回调中调用 next()

javascript - 两个脚本出现 Jade 渲染错误,Uncaught SyntaxError : Unexpected token <

javascript - 这个选择器之间有什么区别吗

facebook - Meteor 无法访问个人资料图片

javascript - 如何在回调中访问正确的“this”?

javascript - 传递带有连字符的字符串被评估为整数(减法!)js

javascript - 使用 ngMouseover 去抖动

node.js - Electron 应用程序应如何处理 OAuth 回调