如何在 node.js 中创建非阻塞异步函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2878008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how do i create a non-blocking asynchronous function in node.js?
提问by Richard
How do I create a non-blocking asynchronous function? Below is what I'm trying to achieve but my program is still blocking...
如何创建非阻塞异步函数?以下是我正在努力实现的目标,但我的程序仍在阻塞...
var sys = require("sys");
function doSomething() {
sys.puts("why does this block?");
while(true);
}
setTimeout(doSomething,0);
setTimeout(doSomething,0);
setTimeout(doSomething,0);
sys.puts("main");
回答by s4y
Cross-posted from Reddit.
从Reddit交叉发布。
The purpose of asynchronous functions in JavaScript is a little bit different from what you seek.
JavaScript 中异步函数的目的与您所寻求的略有不同。
Remember that JavaScript is single-threaded — it can only do one thing at a time. Here is some traditional, blocking code:
请记住,JavaScript 是单线程的——它一次只能做一件事。这是一些传统的阻塞代码:
sys.puts("Before");
sleep(10);
sys.puts("After");
In a real-world web application, the sleep()might instead be a time-consuming database call, network request (like waiting for data from the user's web browser), helper tool, or file access.
在实际的 Web 应用程序中,这sleep()可能是耗时的数据库调用、网络请求(例如等待来自用户 Web 浏览器的数据)、帮助工具或文件访问。
If you used blocking calls like the above, the Node.js server would't be able to do anything else (like starting to handle other web requests) while waiting.
如果您使用上述阻塞调用,则 Node.js 服务器在等待期间将无法执行任何其他操作(例如开始处理其他 Web 请求)。
PHP and many other web programming environments handle this by creating totally separate threads for each request. Node.js uses callback functions. You could write the same code like this, instead:
PHP 和许多其他 Web 编程环境通过为每个请求创建完全独立的线程来处理这个问题。Node.js 使用回调函数。你可以像这样编写相同的代码,而不是:
sys.puts("Before");
setTimeout(function(){
sys.puts("After");
}, 10000);
Here, you create a function and pass it to setTimeout(). Its code hasn't run yet, but when it does, it will have access to all the scope (all the variables) where it was created. setTimeout()gets a reference to the function and schedules an event to fire on the event loopafter the timeout expires.
在这里,您创建一个函数并将其传递给setTimeout(). 它的代码还没有运行,但是当它运行时,它将可以访问创建它的所有范围(所有变量)。setTimeout()获取对该函数的引用,并在超时到期后安排在事件循环上触发的事件。
The event loop is, essentially, a Node.js program's to-do list (they're common — all the GUI applications running on your computer probably use event loops!).
事件循环本质上是一个 Node.js 程序的待办事项列表(它们很常见——在您的计算机上运行的所有 GUI 应用程序都可能使用事件循环!)。
After the call to setTimeout(), the current function keeps executing. It eventually returns, and the function which called it returns, and so on, until the program ends up back in the event loop. The event loop looks to see if anything has happened (e.g. an incoming request) while your code was executing, and calls the appropriate function in your code. If not, it waits until something doeshappen (like the timeout expiring).
调用 后setTimeout(),当前函数继续执行。它最终返回,调用它的函数返回,依此类推,直到程序返回到事件循环中。事件循环查看在您的代码执行时是否发生了任何事情(例如传入的请求),并在您的代码中调用适当的函数。如果不是,它会等待直到有没有发生(如超时到期)。
Asynchronous code doesn'tlet your code do many things at the same time, it doeseliminate blocking when some code depends on something external to continue.
异步代码不会让你的代码同时做很多事情,当一些代码依赖于外部的东西来继续时,它确实消除了阻塞。
It's rare that you need to do blocking work inside your Node.js program. If you do, you should separate that work out into a separate process (which can even be another Node.js program), or write a C/C++ addonwhich is free to use threads.
您很少需要在 Node.js 程序中进行阻塞工作。如果你这样做了,你应该把这个工作分成一个单独的进程(它甚至可以是另一个 Node.js 程序),或者编写一个可以免费使用线程的 C/C++ 插件。
回答by nponeccop
You can only do asynchronous IO in node.js by using asynchronous IO functions provided by node.js runtime or node.js extensions written in C++. Your own Javascript code is always synchronous in node.js. Asynchronous non-IO code is rarely needed, and node.js designers decided to avoid it at all.
只能使用 node.js 运行时或用 C++ 编写的 node.js 扩展提供的异步 IO 函数在 node.js 中进行异步 IO。您自己的 Javascript 代码在 node.js 中始终是同步的。很少需要异步非 IO 代码,node.js 设计者决定完全避免它。
There are some arcane ways of running Javascript asynchronously in node.js, mentioned by other commenters, but node.js is not designed for this type of work. Use Erlang if you need that type of concurrency, node.js is only about paralell IO, and for parallel computations it is just as bad as Python or PHP.
其他评论者提到了在 node.js 中异步运行 Javascript 的一些神秘方法,但 node.js 不是为此类工作而设计的。如果您需要这种类型的并发,请使用 Erlang,node.js 仅与并行 IO 有关,而对于并行计算,它与 Python 或 PHP 一样糟糕。
回答by Felix Geisend?rfer
You need to run your blocking function in a separate process.
您需要在单独的进程中运行您的阻塞功能。
This module can help: http://github.com/cramforce/node-worker
这个模块可以帮助:http: //github.com/cramforce/node-worker
回答by b_erb
If you don't want to use the WebWorker API / node-worker, which is still very alpha, just create an additional node program and communicate via TCP or HTTP.
如果你不想使用 WebWorker API / node-worker,它仍然非常 alpha,只需创建一个额外的节点程序并通过 TCP 或 HTTP 进行通信。
This allows you to dispatch your work as HTTP calls or raw TCP data and asynchronously wait for the HTTP response / incoming TCP answer.
这允许您将您的工作作为 HTTP 调用或原始 TCP 数据分派,并异步等待 HTTP 响应/传入 TCP 响应。
Note however, this is only appropriate if your task is easily serializable.
但是请注意,这仅适用于您的任务易于序列化的情况。
回答by kennytm
setTimeoutwill not create a new thread, so the browser will still hang at the infinite loop.
setTimeout不会创建新线程,所以浏览器仍然会死循环。
You need to rethink your program structure.
你需要重新考虑你的程序结构。
回答by ControlAltDel
You can do this without using a child process using nextTick()
您可以使用 nextTick() 在不使用子进程的情况下执行此操作
I was just reading this explanation the other day about nextTick... it's a great read IMO
前几天我正在阅读关于 nextTick 的这个解释......这是一个很棒的阅读 IMO
---edit: old link is dead. Found a new one right on StackOverflow
---编辑:旧链接已死。在 StackOverflow 上找到了一个新的
回答by Sheraff
If i do understand what you're after, you have two functions (both take a callback as argument):
如果我确实明白你在追求什么,你有两个函数(都以回调作为参数):
process.nextTick: this function can be stacked, meaning that if it is called recursively, it will loop a huge (process.maxTickDepth) number of times per tick of the event loop.
process.nextTick:这个函数可以堆叠,这意味着如果它被递归调用,它将process.maxTickDepth在事件循环的每个滴答中循环大量 ( ) 次。
or
或者
setImmediate: this function is much closer to setting a 0 timeout (but happens before).
setImmediate:这个函数更接近于设置 0 超时(但发生在之前)。
In most cases, you should prefer setImmediate.
在大多数情况下,您应该更喜欢 setImmediate。
回答by murali krish
I am assuming you are experimenting with Nodejs also I am assuming that you are not writing any npm module itself and exporting your function as asynchronous function, In practical you will not encounter such case, if you want to do any blocking operations in the functions or in the callbacks which are executed in a single thread environment, try to use appropriate node modules like fs for file reading, request for network request and async module which gives various types of async operations, also remember you are trying to execute cpu consuming code asynchronously it is a bad idea, because 2HZ can execute a million lines of code in just less than microseconds
我假设您正在尝试使用 Nodejs 也假设您没有编写任何 npm 模块本身并将您的函数导出为异步函数,实际上您不会遇到这种情况,如果您想在函数中执行任何阻塞操作或在单线程环境中执行的回调中,尝试使用适当的节点模块,如 fs 文件读取、网络请求请求和提供各种类型异步操作的 async 模块,还要记住您正在尝试异步执行 CPU 消耗代码这是一个坏主意,因为 2HZ 可以在不到几微秒的时间内执行一百万行代码
The main purpose of nodejs is to solve the problem you have asked in the question which is handled by the underlying libuv to handle asynchronous events, I appreciate the answer of using set time out, but you do not know how much time to wait for or using node worker is fine but you will end up writing lot of boiler plate code, so simply search for the npm module that would satisfy your need.
nodejs的主要目的是解决您在问题中提出的问题,由底层libuv处理来处理异步事件,我很欣赏使用set time out的答案,但您不知道要等待多少时间或使用 node worker 很好,但你最终会写很多样板代码,所以只需搜索满足你需求的 npm 模块。
回答by Matt Ranney
This line:
这一行:
while(true);
isn't "blocking", it's just busy, forever.
不是“阻塞”,它只是忙,永远。

