// synchronous Javascript var result = db.get(‘select * from table1’); console.log(‘I am syncronous’);
// asynchronous Javascript db.get('select * from table1', function(result){ // do something with the result }); console.log('I am asynchronous')
我知道在同步代码中,console.log()在从数据库中获取结果之后执行,而在异步代码中,console.log()在db.get()获取结果之前执行。
现在我的问题是,异步代码在后台如何执行?为什么非阻塞呢?
我搜索了Ecmascript 5标准,以了解异步代码的工作原理,但在整个标准中找不到异步一词。
从nodebeginner.org上,我还发现我们不应该使用return语句,因为它会阻塞事件循环。但是nodejs api和第三方模块到处都包含return语句。那么什么时候应该使用return语句,什么时候不应该使用它?
有人可以对此有所启发吗?
首先,将函数作为参数传递就是告诉您正在调用的函数,希望将来某个时候调用该函数。确切的将来何时调用该函数取决于函数正在执行的操作的性质。
如果该函数正在进行一些联网,并且该函数配置为非阻塞或异步,则该函数将执行,将开始联网操作,并且您调用的函数将立即返回,而其余的内联javascript代码将在返回之后该功能将执行。如果从该函数返回一个值,则该值将立即返回,很早在调用作为参数传递的函数之前(联网操作尚未完成)。
同时,网络操作正在后台进行。它正在发送请求,侦听响应,然后收集响应。当网络请求完成并且已收集响应时,然后,然后您调用的原始函数将调用您作为参数传递的函数。这可能只是几毫秒后,也可能是几分钟后,这取决于网络操作完成的时间。
重要的是要理解,在您的示例中,db.get()函数调用已经完成很长时间了,执行完之后的代码也依次执行。尚未完成的是您作为参数传递给该函数的内部匿名函数。这一直保存在javascript函数闭包中,直到以后网络功能结束。
db.get()
我认为,使很多人感到困惑的一件事是,匿名函数在您对db.get的调用中声明,并且似乎是该函数的一部分,并且当db.get()完成后似乎也会这样做,但这就是并非如此。如果以这种方式表示,则可能看起来不太像:
function getCompletionfunction(result) { // do something with the result of db.get } // asynchronous Javascript db.get('select * from table1', getCompletionFunction);
然后,也许更明显的是db.get将立即返回,并且getCompletionFunction将在将来的某个时间被调用。我不建议您以这种方式编写它,而只是显示此表单以说明实际情况。
这是一个值得理解的序列:
console.log("a"); db.get('select * from table1', function(result){ console.log("b"); }); console.log("c");
您将在调试器控制台中看到以下内容:
a c b
“ a”首先发生。然后,db.get()开始其操作,然后立即返回。因此,“ c”接下来发生。然后,当db.get()操作实际上在将来的某个时间完成时,就会发生“ b”。