Nodejsasynchronous和同步读写文件 – 何时使用?

这是一个非常普遍的问题,但我不太明白。 我什么时候会比另一个更喜欢? 我似乎不明白可能会出现什么情况,这显然会比较有利于彼此。 是否有充分的理由避免x /使用x?

我什么时候会比另一个更喜欢?

使用非Sync版本(asynchronous版本),除非在I / O挂起期间没有其他任何事情需要您的程序执行,在这种情况下, Sync版本可以正常工作; 详情见下文…

是否有充分的理由避免x /使用x?

是。 NodeJS在一个线程上运行你的JavaScript代码。 如果使用I / Ofunction的Sync版本,则该线程被阻塞,等待I / O,并且无法执行其他任何操作。 如果使用asynchronous版本,那么I / O可以在JavaScript线程继续执行其他工作时在后台继续; I / O完成将作为JavaScript线程的作业排队等待以后返回。

如果您正在运行一个前台Node应用程序,在I / O挂起时不需要做任何事情,那么使用Sync调用可能就不错了。 但是,如果您使用Node一次处理多个事件(如Web请求),最好使用asynchronous版本。

在您所说的问题下添加的评论:

我想到了一个使用nodejs的电子应用程序,它只是简单地阅读一个文件,不知道如果我的软件真的需要等待这个文件加载,那么这个文件会有什么不同。

我几乎没有Electron的知识,但我注意到它使用“主”过程来pipe理窗口,然后每个窗口( 链接 )的“渲染”过程。 在这种情况下,使用Syncfunction会阻止相关进程,这可能会影响应用程序或窗口的响应。 但是我对Electron没有深刻的认识(更多的可惜)。


直到最近,使用asynchronous函数意味着使用很多难以编写的callback代码:

 // (Obviously this is just an example, you wouldn't actually read and write a file this way, you'd use streaming...) fs.readFile("file1.txt", function(err, data) { if (err) { // Do something about the error... } else { fs.writeFile("file2.txt", data, function(err) { if (err) { // Do something about the error... } else { // All good }); } }); 

然后承诺出现了,如果你使用了promisified *版本的操作(在这里显示假名像fs.promisifiedXYZ ),它仍然涉及callback,但他们更可组合:

 // (See earlier caveat, just an example) fs.promisifiedReadFile("file1.txt") .then(function(data) { return fs.promisifiedWriteFile("file2.txt", data); }) .then(function() { // All good }) .catch(function(err) { // Do something about the error... }); 

现在,在Node的最新版本中,可以使用ES2017 + async / await语法来编写实际上是asynchronous代码的同步代码:

 // (See earlier caveat, just an example) (async () => { try { const data = await fs.promisifiedReadFile("file1.txt"); fs.promisifiedWriteFile("file2.txt", data); // All good } catch (err) { // Do something about the error... } })(); 

节点的API早于承诺,并有其自己的约定。 有各种各样的库,以帮助你“promisify”一个节点式的callbackAPI,所以它使用承诺,而不是。 一个是promisify但也有其他人。

我什么时候会比另一个更喜欢?

在旨在扩展和满足许多用户需求的服务器中,只能在服务器初始化期间使用同步I / O。 事实上, require()本身使用同步I / O。 在服务器的所有其他部分处理传入的请求,一旦服务器已经启动并运行,您将只使用asynchronousI / O。

除了创build服务器之外,node.js还有其他用途。 例如,假设你想创build一个脚本,通过一个巨大的文件parsing并查找特定的单词或短语。 而且,这个脚本被devise成独立运行来处理一个文件,并且它没有持久的服务器function,并且没有特别的理由一次做多个来源的I / O。 在这种情况下,使用同步I / O是完全正确的。 例如,我创build了一个node.js脚本来帮助我规划备份文件(删除符合某些特定年龄标准的备份文件),然后我的电脑每天自动运行一次该脚本。 没有理由使用asynchronousI / O作为这种types的使用,所以我使用同步I / O,它使得代码更容易编写。

我似乎不明白可能会出现什么情况,这显然会比较有利于彼此。 是否有充分的理由避免x /使用x?

避免在服务器的请求处理程序中使用同步I / O。 由于node.js中的Javascript的单线程性质,使用同步I / O阻塞node.js Javascript线程,所以它一次只能做一件事(这对于多用户服务器来说是死的),而asynchronousI / O不阻止node.js Javascript线程(允许它可能服务于许多用户的需求)。

在非多用户情况下(对一个用户只做一件事的代码),同步I / O可能会受到欢迎,因为编写代码更容易,使用asynchronousI / O可能没有优势。

我想到了一个使用nodejs的电子应用程序,它只是简单地阅读一个文件,不知道如果我的软件真的需要等待这个文件加载,那么这个文件会有什么不同。

如果这是一个单用户应用程序,并且在等待文件读入内存时没有其他任何事情可以让您的应用程序进行操作(无需响应的套接字,没有屏幕更新,没有其他请求正在处理,没有其他文件操作并行运行),那么使用asynchronousI / O没有任何优势,所以同步I / O将会很好,并且可能会更简单一些。