async.waterfall和child_process.execSync有什么区别?

时间:2016-06-06 18:42:54

标签: node.js

如果这是linux shell,我想做的是:

copy file1 tmp
rename tmp file2

我可以做瀑布

function copyFile(cb) {
    child_process.exec('cp file1 tmp', function (error, stdout, stderr) {
        ......
    });
}
async.waterfall([
    copyFile,
    renameFile
], function (error) {
    if (error) {
        //handle readFile error or processFile error here
    }
});

或猜测我能做到

child_process.execSync('cp file1 tmp");
child_process.execSync('rename tmp file2');

请问有什么区别?例如表现?阻止? 非常感谢!

1 个答案:

答案 0 :(得分:2)

这里的主要区别是execSync,它会阻塞,exec会阻塞。 execSync阻止创建过程,直到使用execSync创建的child_process返回。 exec会立即返回并返回一个值(如果以后有一个值)并且不会阻止创建父进程。否则,它们在阻塞之外的行为方式是相同的。

async.waterfall是一种控制流机制,它只保证操作按顺序执行,链返回值从链中的第一个函数到链中的最后一个函数。如果传递给async.waterfall的其中一个函数包含阻塞的代码,那么async.waterfall也将被阻止。 async.waterfall并不保证在其中执行的所有代码都是异步的。

使用child_process意味着这将在单独的进程上执行,而不是在使用node执行的主进程上执行。您不应该使用child_process来控制流,因为与创建和销毁新子进程相关的开销很大。除非您正在执行一些CPU密集型任务或需要单独的流程,否则应该避免这种情况。

如果你想同步执行某些事情,你可以将所有代码包装在try/catch块中,但我肯定会说不要使用child_process来控制流程。

从性能角度来看,这两种方法都很糟糕,因为它们创建了一个child_process但是exec()会更好,因为它至少会立即返回到创建过程,从而允许其他代码继续执行。每当在Node中使用阻塞代码时,您就消除了使用Node的主要好处。在某些情况下需要阻塞,例如需要模块,但在大多数情况下,存在非阻塞替代方案。

另外,如果您尝试复制文件,可以使用fs模块并将原始文件通过新名称传输到新目标中的新文件中。以下方法是异步的,并且不需要任何外部依赖项或控制流库。此外,它应该比您在上面实现的任何代码更高效。

var fs = require('fs');

function copy (src, dest, callback) {
    var r = fs.createReadStream(src);
    var w = fs.createWriteStream(dest);

    r.pipe(w);

    r.on('error', function() {
        return callback(err);
    });

    r.once('end', function() {
        return callback();
    });
}