简体   繁体   English

条件异步回调

[英]Conditional async callbacks

I'm writing an Electron program which takes a CSV file as input, and does file operations depending on the CSV content and file existence (it's to manage MAME arcade roms). 我正在编写一个Electron程序,该程序将CSV文件作为输入,并根据CSV内容和文件存在(执行MAME arcade rom)进行文件操作。

In order to have a progress bar on the UI side, I have switched the code from fully synchronous (because it was much easier) to asynchronous. 为了在UI端具有进度条,我将代码从完全同步(因为它更容易)切换为异步。

I just cannot find out how to reliably display a message to the user when all the lines in the CSV file are processed, and all the zip files are copied or removed. 当处理CSV文件中的所有行以及复制或删除所有zip文件时,我只是无法确定如何可靠地向用户显示消息。

Here is a (simplified) sample method: 这是一个(简化的)样本方法:

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
        }
    });
});

The problem is that the CSV file is processed really fast, but the file are not copied as fast. 问题在于CSV文件的处理速度非常快,但是文件复制速度却不如之前快。 So it decrements the lines counter to 0, then after each file copy, it finds that it's zero and triggers the callback. 因此,它将lines计数器递减为0,然后在每次复制文件后,发现它为零并触发回调。

How do I reliably trigger the callback at the end of all these nested callbacks and conditions? 如何在所有这些嵌套的回调和条件结束时可靠地触发回调?

Thanks 谢谢

I tried to change the code without massively overwriting your style - assuming there is a reason to avoid things like bluebird , async/await & native Promises, and the async lib. 我试图在不大量覆盖样式的情况下更改代码-假设有理由避免诸如bluebird ,async / await和本机Promises之类的东西以及async库。

You need to decrement lines after a line is processed. 处理一行后,您需要减少行数。 I pulled the processing logic out into a function to make this clearer: 我将处理逻辑提取到一个函数中以使其更加清晰:

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();
            }
        }})
    });
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM