开发者

how do i create a non-blocking asynchronous function in node.js?

开发者 https://www.devze.com 2022-12-31 17:32 出处:网络
How do I create a non-blocking asynchronous function? Below is what I\'m trying to achieve but my program is still blocking...

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?");
  开发者_JS百科while(true);
}

setTimeout(doSomething,0);
setTimeout(doSomething,0);
setTimeout(doSomething,0);

sys.puts("main");


Cross-posted from Reddit.


The purpose of asynchronous functions in JavaScript is a little bit different from what you seek.

Remember that JavaScript is single-threaded — it can only do one thing at a time. Here is some traditional, blocking code:

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.

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.

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:

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 loop after the timeout expires.

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!).

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 does happen (like the timeout expiring).

Asynchronous code doesn’t let your code do many things at the same time, it does eliminate 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++ addon which is free to use threads.


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.

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.


You need to run your blocking function in a separate process.

This module can help: http://github.com/cramforce/node-worker


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.

This allows you to dispatch your work as HTTP calls or raw TCP data and asynchronously wait for the HTTP response / incoming TCP answer.

Note however, this is only appropriate if your task is easily serializable.


setTimeout will not create a new thread, so the browser will still hang at the infinite loop.

You need to rethink your program structure.


You can do this without using a child process using nextTick()

I was just reading this explanation the other day about nextTick... it's a great read IMO

---edit: old link is dead. Found a new one right on StackOverflow

understanding the node.js event queue and process.nextTick


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.

or

setImmediate: this function is much closer to setting a 0 timeout (but happens before).

In most cases, you should prefer setImmediate.


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

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.


Try to answer this question based on the event loop model (the core of node.js).

setTimeout(doSomething,0). Yes, setTimeout will add a task into the task queue. And after 0 second, the time is up. Event loop checks the task queues and finds the task is done, and its callback function doSomething is ready to run.

The above process is async.

One thing needs to note here is: the callback function doSomething runs on the main thread(or the single thread) of node.js, and the event loop is also running on this thread. Without a doubt, the while(true) loop totally block the thread.


This line:

while(true);

isn't "blocking", it's just busy, forever.

0

精彩评论

暂无评论...
验证码 换一张
取 消