Prescriptive Node.js

Bry*_*yle 27 javascript node.js

我最近一直在开始使用Node.js而且我遇到过一种情况,我需要一些关于规定node.js完成任务的方法的指导.在这种特殊情况下,我需要创建一堆目录,当所有目录都已创建时,我需要执行一些最终操作.创建目录的顺序无关紧要,我只需要在最后一个操作后执行最后的操作.

实现这一目标的最简单方法是回归旧的同步习惯.也就是说,只需调用fs.mkdirSync每个目录并在最后执行操作.例如:

fs.mkdirSync('a', 0755);
fs.mkdirSync('a/b', 0755);
fs.mkdirSync('a/b/c', 0755);
performFinalOperation();
Run Code Online (Sandbox Code Playgroud)

虽然这会起作用,但感觉不像是node.js这样做的方式.显然,程序会在等待操作系统创建目录并返回时阻塞.在负载较重的系统上,远程安装的文件系统mkdirSync可能需要很长时间.很明显,这不是最好的方法.

Node.js的一个主要卖点是它是异步的.所以调用fs.mkdir可以通过回调链接:

fs.mkdir('a', 0755, function(e) {
    if (!e) {
        fs.mkdir('a/b', 0755, function(e) {
            if (!e) {
                fs.mkdir('a/b/c', 0755, function(e) {
                    if (!e) {
                        performFinalOperation();
                    }
                });
            }
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

同样,这种方法我确定有效,但它会导致非常深的嵌套和代码重复.它确实具有在创建目录时不阻塞的好处,但成本是多少?

另一种方法是真正想要避免代码重复和嵌套:

(function (directories) {
    if (directories.length === 0) {
        performFinalOperation();
    } else {
        var tail = arguments.callee;
        fs.mkdir(directories.shift(), 0755, function(e) {
            tail(directories);
        });
    }
})(['a', 'a/b', 'a/b/c']);
Run Code Online (Sandbox Code Playgroud)

这种方法利用了各种疯狂的东西:匿名自我调用函数和神奇的arguments.callee.但最糟糕的是,乍看之下代码的作用并不明显.

因此,虽然具体问题是创建目录,但我更感兴趣的是经验丰富的node.js老手在出现这种情况时会采取的方法.我特别关心库是什么让这更容易.

Adr*_*ien 19

您的第二个解决方案可以大大简化,并包含以下错误:

var mkdirs = function(dirs, mode, cb){
  (function next(e) {
    (!e && dirs.length) ? fs.mkdir(dirs.shift(), mode, next) : cb(e);
  })(null);
};
Run Code Online (Sandbox Code Playgroud)


sub*_*ack 9

npm install mkdirp

var mkdirp = require('mkdirp').mkdirp;

mkdirp('/tmp/foo/bar/baz', 0755, function (err) {
    if (err) console.error(err)
    else console.log('pow!')
});
Run Code Online (Sandbox Code Playgroud)


Sam*_*uri 6

哦,嘿布莱恩:)

我特别不关心库是什么让这更容易.

经验丰富的Node退伍军人已经编写了至少一个自己的控制流库.我们刚刚复制了Twisted的Deferred类,因为他们已经完成了异步编程的艰苦工作和研究.这反转了标准的callback-as-argument模式,我喜欢结果代码,但如果你想嵌套一堆回调,你仍然可以做到这一点Deferred并最终得到同样多的混乱.

由于不使用图书馆的限制,人们通常完全按照你所写的方式行事.确实没有其他选择.如果没有生成器等语言更改,我们可以做的最好的就是使用库.如果你不想使用现有的,你最终会自己滚动或只是编写很多样板.

  • +1节点的最佳功能之一就是它的模块生态系统.核心保持相当小(不解决所有问题),因此用户区模块可以解决这些问题.这使节点轻量级,灵活且不断发展. (2认同)