Node.jsasynchronous用例
最近,我一直在开发Web应用程序,我意识到我没有使用asynchronous属性。 因此,我结束了很多嵌套的callback。
例如,如果用户想通过特定的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 }); })
这段代码需要查询数据库,以便在asynchronous循环之前获取文件名列表,并将每个文件内容放入一个数组中。 最后它会将完成的数组返回给客户端。
使用嵌套的callback和asynchronous库,这个代码的行为就像是一个同步代码。
names = db.querySync(//select list of permitted files_names); for(name in names) { //open each file to put into array }
我更喜欢写这样的同步代码,因为它很整洁。 我的用例可能有点奇怪,但我的API的大部分行为以类似的方式,这让我想为什么我甚至需要asynchronousfunction?
如果这两个编码在performance上有差异,有谁能指教我? 如何使用非阻塞属性来提高此用例的性能?
如果你正在使用asynchronous调用来定义你正在使用的callback函数。 callback函数只在操作完成或出错时触发。 您不需要一个花哨的库来使用它们,这是Node的事件循环驱动子系统如何操作的骨干。
节点强烈build议不要使用“同步”呼叫。 Node核心只包括一小部分作为方便,他们作为最后的手段工具。 许多库甚至不支持它们,所以你绝对必须习惯编写asynchronous代码。 例如,在浏览器环境中,您无法使用阻止调用,而不会干扰JavaScript运行时并拖延页面。
我更喜欢使用Promises line Bluebird实现有序地保持代码。 还有其他的方法,像asynchronous库,可以帮助pipe理复杂的嵌套模式。
一些特权包括Promise.all
方法运行一系列承诺完成,然后触发下一步, Promise.map
迭代列表,为每个元素运行asynchronous代码,然后在列表完成时推进。
如果你有组织你的代码的纪律,这不是太糟糕。 Node比Ruby,Python或Java等传统的默认同步语言要求更多地关注操作的顺序,但是您可以习惯它。 一旦开始使用asynchronous代码而不是与之对抗,通常可以快速,高效地完成大量工作,并且在许多情况下比其他语言更有效,这些语言中必须处理线程以及locking和/或处理与IPC。
好处很简单:通过使用asynchronous代码,当前线程(记住,Node.js是单线程的)能够处理其他请求,而当前请求正在等待某个事件(如数据库查询)返回。
如果使用同步代码,当前线程将在等待时阻塞,同时将无法处理其他请求。 换句话说,你失去了并发性。
为了保持asynchronous代码的清洁,请查看承诺(避免深度嵌套的callback)和ES7asynchronous/等待(以避免callback,并编写看起来像同步代码的asynchronous代码)。
是的,两个代码在性能方面有所不同。
在同步代码中:
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秒的总时间。
而在asynchronous代码中:
db.query(<select list of permitted files_names>, function(err, filenames) {
NodeJs会要求数据库给一个callback名字列表。 假设需要10秒。 并立即进入下一步(某些代码),但不进入阻塞状态。 假设一些代码需要5秒。
async.each(file_names, function(name, next) { //open each file to put into array }); }) //some code.
5秒后,它将检查是否有I / O操作要执行。 一旦回电被返回。 它会在5秒内执行函数(name,next){..}。
所以这里的总时间是15秒。
以这种方式,性能得到改善。
如果asynchronous代码应该清晰整齐,那么就使用闭包和承诺。
例如:上面的asynchronous代码可以写成
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);