为什么Node.js同时具有async和amp;同步版本的fs方法?

时间:2014-02-06 18:34:58

标签: node.js

在Node.js中,我几乎可以通过以下两种方式执行任何异步操作:

var file = fs.readFileSync('file.html')

...或

var file
fs.readFile('file.html', function (err, data) {
  if (err) throw err
  console.log(data)
})

异步一个自定义错误处理的唯一好处是什么?或者是否真的有理由让文件读取操作无阻塞?

4 个答案:

答案 0 :(得分:4)

这些主要是因为节点本身需要它们在程序启动时从磁盘加载程序的模块。更广泛地说,通常在服务最初启动时但在接受网络连接之前进行一组同步设置IO。一旦程序准备就绪(加载了TLS证书,读取了配置文件等),就会绑定一个网络套接字,此时所有内容都是异步的。

答案 1 :(得分:3)

异步调用允许执行链的分支以及通过该执行链传递结果。这有很多好处。

首先,程序可以同时执行两个或多个调用,并在结果完成时对结果进行处理,不一定按照首次调用的顺序进行。

例如,如果您有一个程序在等待两个事件:

var file1;
var file2;

//Let's say this takes 2 seconds
fs.readFile('bigfile1.jpg', function (err, data) {
  if (err) throw err;
  file1 = data;
  console.log("FILE1 Done");
});    

//let's say this takes 1 second.
fs.readFile('bigfile2.jpg', function (err, data) {
  if (err) throw err;
  file2 = data;
  console.log("FILE2 Done");
});

console.log("DO SOMETHING ELSE");

在上面的情况中,bigfile2.jpg将首先返回,并且仅在1秒后将记录一些内容。所以你的输出时间表可能是这样的:

@0:00: DO SOMETHING ELSE
@1:00: FILE2 Done
@2:00: FILE1 Done

请注意,上面记录了“DO SOMETHING ELSE”的日志。并且File2仅在1秒后执行...并且在2秒后File1完成。尽管callBack订单无法预测,但所有内容都在总共2秒内完成。

虽然同步地执行它看起来像:

file1 = fs.readFileSync('bigfile1.jpg');
console.log("FILE1 Done");
file2 = fs.readFileSync('bigfile2.jpg');
console.log("FILE2 Done");
console.log("DO SOMETHING ELSE");

输出可能如下:

@2:00: FILE1 Done
@3:00: FILE2 Done
@3:00  DO SOMETHING ELSE

注意执行总共需要3秒,但顺序就是您调用它的方式。

同步执行通常需要更长时间才能完成所有工作(,特别是对于文件系统读取,写入或数据库请求等外部进程),因为您在等待一件事情完成之前要继续完成下一步。有时你想要这个,但通常你不需要。有时可以更容易同步编程,因为您可以按特定顺序(通常)可靠地执行任务。

异步执行文件系统方法 但是,您的应用程序可以继续执行其他与文件系统无关的任务,而无需等待文件系统进程完成。因此,通常您可以在系统等待异步操作完成时继续执行其他工作。这就是您通常使用异步方法(通常)查找数据库查询,文件系统和通信请求的原因。它们基本上允许在等待其他(I / O和系统外)操作完成时完成其他工作。

当你进入更高级的异步方法链接时,你可以做一些非常强大的事情,比如用少量代码创建范围(使用闭包等),并为某些事件循环创建响应者。

很抱歉答案很长。有许多理由可以选择同步或不同步,但希望这可以帮助您确定这两种方法是否最适合您。

答案 2 :(得分:0)

异步版本的好处是,您可以在等待IO完成时执行其他操作。

fs.readFile('file.html', function (err, data) {
  if (err) throw err;
  console.log(data);
});

// Do a bunch more stuff here. 

// All this code will execute before the callback to readFile, 
// but the IO will be happening concurrently. :)

答案 3 :(得分:0)

当您编写事件驱动的代码时,您希望使用异步版本,以便快速响应请求是最重要的。 Node的规范示例是编写Web服务器。假设您有一个用户发出请求,这样服务器就必须执行一堆IO。如果同步执行此IO,则服务器将阻止。在完成请求之前,它不会回答任何其他请求。从用户的角度来看,性能似乎很糟糕。因此,在这种情况下,您希望使用调用的异步版本,以便Node可以继续处理请求。

IO调用的同步版本存在,因为Node不用于 来编写事件驱动的代码。例如,如果您正在编写一个实用程序来读取文件,修改它并将其作为批处理操作的一部分写回磁盘,就像命令行工具一样,使用IO操作的同步版本可以使您的代码更容易跟随。