这篇文章是从Reddit转载而来。
JavaScript中异步函数的目的与您所寻求的有些不同。
请记住,JavaScript是单线程的——它一次只能做一件事情。以下是一些传统的阻塞代码:
sys.puts("Before");
sleep(10);
sys.puts("After");
在现实的网络应用程序中,sleep()
可能会变成耗时的数据库调用、网络请求(比如等待用户的Web浏览器传输数据)、辅助工具或文件访问。
如果使用像上述那样的阻塞调用,Node.js 服务器将无法在等待期间执行其他任何操作(例如开始处理其他网络请求)。
PHP 和许多其他 Web 编程环境通过为每个请求创建完全独立的线程来处理此问题。Node.js 使用回调函数。您可以按照以下方式重写相同的代码:
sys.puts("Before");
setTimeout(function(){
sys.puts("After");
}, 10000);
在这里,您创建一个函数并将其传递给 setTimeout()
。它的代码尚未运行,但是当它运行时,它将可以访问创建它的所有作用域(所有变量)。setTimeout()
获取对该函数的引用,并安排在超时到期后在事件循环上触发事件。
事件循环本质上就是 Node.js 程序的待办事项列表(它们很常见——运行在计算机上的所有 GUI 应用程序可能都使用事件循环!)。
在调用 setTimeout()
后,当前函数继续执行。最终返回,调用它的函数也返回等等,直到程序回到事件循环中。事件循环查看是否有任何事情发生(例如传入请求),而您的代码正在执行,并调用您的代码中适当的函数。如果没有,则等待直到发生某些事情(例如超时到期)。
异步代码不会让您的代码同时执行多个任务,但是当某些代码依赖于外部因素才能继续时,可以消除阻塞。
在您的 Node.js 程序中很少需要执行阻塞工作。如果确实需要,请将该工作分离到另一个进程中(甚至可以是另一个 Node.js 程序),或编写C/C++插件,它可以自由使用线程。