最近,我一直在开发Web应用程序,我意识到我根本没有使用异步属性。因此,我最终会遇到很多嵌套回调。
例如,如果用户想通过特定API从服务器获取文件,我将使用与此类似的代码,
db.query(<select list of permitted files_names>, function(err, filenames) {
async.each(file_names, function(name, next) {
//open each file to put into array
});
})
此代码需要在异步循环并将每个文件内容放入数组之前查询数据库以获取文件名列表。最后,它会将完成的数组返回给客户端。
使用嵌套回调和异步库,此代码的行为类似于同步代码。
names = db.querySync(//select list of permitted files_names);
for(name in names) {
//open each file to put into array
}
我最好写这样的同步代码,因为它更整洁。我的用例可能有点奇怪,但我的大多数api都以类似的方式运行,这让我觉得为什么我甚至需要异步函数?
如果这两个代码在性能方面有任何差异,有人可以告诉我吗?如何利用非阻塞属性来提高此用例的性能?
答案 0 :(得分:3)
如果您正在编写回调函数,那么您可以使用异步调用来定义它。操作完成或出错时,回调函数仅触发 。您不需要花哨的库来使用它们,这是Node event-loop driven subsystem运行方式的支柱。
节点强烈建议不要使用“同步”来电。 Node核心只包含少数几个便利,它们是最后的工具。许多库甚至不支持它们,所以你绝对必须习惯编写异步代码。例如,在浏览器环境中,您根本无法使用阻塞调用而不会干扰JavaScript运行时并停止页面。
我更喜欢使用Promises行Bluebird工具来保持代码有序。还有其他方法,比如async库,可以帮助管理其他复杂的嵌套模式。
一些特权包括Promise.all
方法运行一系列承诺完成然后触发下一步,Promise.map
迭代列表,为每个元素运行异步代码,然后列表完成后推进。
如果你对组织代码有所规定,那就不算太糟糕了。与传统的默认语言(如Ruby,Python或Java)相比,Node确实需要更多关注操作顺序,但您可以习惯它。一旦你使用异步代码开始使用而不是对抗它,你通常可以快速,高效地完成大量工作,并且在很多情况下比在其他必须兼顾的语言中更有效。线程加锁定和/或处理IPC。
答案 1 :(得分:3)
是的,两个代码在性能方面存在差异。
在同步代码中:
names = db.querySync(//select list of permitted files_names);
您在此处调用数据库以提供名称列表。假设这需要10秒。所以在这个时候,nodeJS因为它是单线程gos进入阻塞状态。 10秒后,它执行剩下的代码。假设这个for循环需要5秒,而某些代码需要5秒。
for(name in names) {
//open each file to put into array
}
//some code
因此总时间为20秒。
而在异步代码中:
db.query(<select list of permitted files_names>, function(err, filenames) {
NodeJs会要求数据库为回调提供名称列表。假设需要10秒。并立即进入下一步(某些代码),但不进入阻塞状态。假设某些代码需要5秒。
async.each(file_names, function(name, next) {
//open each file to put into array
});
})
//some code.
5秒后,它将检查是否有要执行的i / o操作。一旦回叫退回。它将执行5秒的函数(名称,下一个){..}。
所以这里的总时间是15秒。
通过这种方式,性能得到了提升。
如果异步代码应该清晰整洁,那么请使用闭包&amp;承诺。
例如:上面的异步代码可以写成
fun = function(err, filenames) {
async.each(file_names, function(name, next) {
//open each file to put into array
}
db.query(<select list of permitted files_names>, fun);
答案 2 :(得分:2)
好处很简单:通过使用异步代码,当前线程(记住,Node.js是单线程的)能够处理其他请求,而当前请求正在等待某些事情(如数据库查询)返回。
如果使用同步代码,当前线程将在等待时阻塞,同时它将无法处理其他请求。换句话说,你失去了并发性。
要保持异步代码干净,请查看promises(以避免深层嵌套回调)和ES7 async / await(以避免回调并编写看起来像同步代码的异步代码)。