2013-05-30 37 views
2

我有一个非常简单的实用程序脚本,我用JavaScript编写了node.js,它读取文件,进行一些计算,然后写入输出文件。在目前形式的源看起来是这样的:我应该在node.js中的本地文件的同步等效项上使用异步文件IO方法吗?

fs.readFile(inputPath, function (err, data) { 
    if (err) throw err; 
    // do something with the data 
    fs.writeFile(outputPath, output, function (err) { 
     if (err) throw err; 
     console.log("File successfully written."); 
    }); 
}); 

这工作得很好,但我不知道是否有在这种情况下,任何不利使用各种同步这些功能,而不是像这样:

var data = fs.readFileSync(inputPath); 
// do something with the data 
fs.writeFileSync(outputPath, output); 
console.log("File successfully written."); 

对我来说,阅读和理解比回调变得简单得多。在这种情况下是否有任何理由使用前一种方法?

我意识到速度并不是一个问题,我用本地运行的这个简单的脚本,但我有兴趣了解它背后的理论。什么时候使用异步方法有帮助,什么时候没有?即使在生产应用程序中,如果我只是在读文件,然后等待执行下一个任务,是否有任何理由使用异步方法?

回答

6

重要的是当同步IO发生时,您的节点进程需要做什么。在单个用户在命令行运行简单的shell脚本的情况下,同步IO是完全正确的,因为如果你在执行异步IO,你所做的就是等待IO返回。

但是,在一个拥有多个用户的网络服务中,您绝对不能使用任何同步IO调用(这是类节点的全部点,所以请相信我)。这样做会导致所有连接的客户端停止处理,并且完成厄运。经验法则:shell脚本:OK,网络服务:verboten!

为了进一步阅读,我在this answer做了几个类比。

基本上,当节点在网络服务器中执行异步IO时,它可以要求操作系统执行许多操作:读取几个文件,进行一些数据库查询,发送一些网络流量,并在等待异步IO准备好了,它可以在主事件线程中执行内存/ CPU的事情。使用这种体系结构,节点获得相当不错的性能/并发性。但是,当同步IO操作发生时,整个节点进程只会阻塞,并且什么都不做。它只是等待。不能接收新的连接。没有处理过程发生,没有事件循环嘀嗒,没有回调,没有任何东西。只有1个同步操作会阻止所有客户端的整个服务器。你一定不要这样做。不管它有多快,或者类似的事情都没有关系。这与本地文件系统或网络请求无关。即使你花费10ms为每个客户端从磁盘读取一个小文件,如果你有100个客户端,客户端100将等待整整一秒,而这个文件一次又一次被客户端1-99读取。

+1

这对我有意义,但你能详细说明网络服务点吗? Node.js是单线程的,对吗?如果是这样,那么如何使用与“异步”不同的同步IO调用?我意识到异步调用会放弃对其他用户的主线程的控制权,但我不太清楚如何(在读取本地文件时)他们将阻止线程同时投入单个客户端。 –

1

异步代码不会阻止执行流程,允许您的程序在等待操作完成时执行其他任务。

在第一个示例中,您的代码可以继续运行而无需等待写入文件。在第二个例子中,代码执行被“阻塞”直到写入文件。这就是为什么同步代码被称为“阻塞”,而异步代码被称为“非阻塞”。