Node JS Express Handling multiple requests - node.js

What I Have:
I have a nodejs express server get endpoint that in turn calls other APIs that are time consuming(say about 2 seconds). I have called this function with a callback such that the res.send is triggered as a part of the call back. The res.send object packs an object that will be created after the results from these time consuming API calls is performed. So my res.send can only be sent when I have the entire information from the API call.
Some representative code.
someFunctionCall(params, callback)
{
// do some asyncronous requests.
Promise.all([requestAsync1(params),requestAsync2(params)]).then
{
// do some operations
callback(response) // callback given with some data from the promise
}
}
app.get('/',function(req, res){
someFunctionCall(params, function(err, data){
res.send(JSON.stringify(data))
}
}
What I want
I want my server to be able to handle other parallel incoming get requests without being blocked due to the REST api calls in the other function. But the problem is that the callback will only be issued when the promises are fulfilled,each of those operations are async, but my thread will wait till the execution of all of them. And Node does not accept the next get request without executing the res.send or the res.end of the previous request. This becomes an issues when I have multiple requests coming in, each one is executed one after another.
Note: I do not want to go with the cluster method, I just want to know if it is possible to this without it.

You are apparently misunderstanding how node.js, asynchronous operations and promises work. Assuming your long running asynchronous operations are all properly written with asynchronous I/O, then neither your requestAsync1(params) or requestAsync2(params) calls are blocking. That means that while you are waiting for Promise.all() to call its .then() handler to signify that both of those asynchronous operations are complete, node.js is perfectly free to run any other events or incoming requests. Promises themselves do not block, so the node.js event system is free to process other events. So, you either don't have a blocking problem at all or if you actually do, it is not caused by what you asked about here.
To see if your code is actually blocking or not, you can temporarily add a simple timer that outputs to the console like this:
let startTime;
setInterval(function() {
if (!startTime) {
startTime = Date.now();
}
console.log((Date.now() - startTime) / 1000);
}, 100)
This will output a simple relative timestamp every 100ms when the event loop is not blocked. You would obviously not leave this in your code for production code, but it can be useful to show you when/if your event loop is blocked.
I do see an odd syntax issue in the code you included in your question. This code:
someFunctionCall(params, callback)
{
// do some asyncronous requests.
Promise.all([requestAsync1(params),requestAsync2(params)]).then
{
// do some operations
callback(response) // callback given with some data from the promise
}
}
should be expressed like this:
someFunctionCall(params, callback)
{
// do some asyncronous requests.
Promise.all([requestAsync1(params),requestAsync2(params)]).then(function(response)
{
// do some operations
callback(response) // callback given with some data from the promise
}
});
But, an even better design would be to just return the promise and not switch back to a plain callback. Besides allowing the caller to use the more flexible promises scheme, you are also "eating" errors that may occur in either or your async operations. It's suggest this:
someFunctionCall(params) {
// do some asyncronous requests.
return Promise.all([requestAsync1(params),requestAsync2(params)]).then(function(results) {
// further processing of results
// return final resolved value of the promise
return someValue;
});
}
Then, then caller would use this like:
someFunctionCall(params).then(function(result) {
// process final result here
}).catch(function(err) {
// handle error here
});

Related

JS: Why Promise then() method executes synchronously?

I need to make part of my method's code asynchronous, so it will execute in a non-blocking manner. For this purpose I've tried to create a "dummy" Promise and put the specified code in then block. I have something like this:
public static foo(arg1, arg2) {
const prom = new Promise((resolve, reject) => {
if (notValid(arg1, arg2)) {
reject();
}
resolve(true);
});
prom.then(() => {
...my code using arg1 and arg2...
});
}
However, then block always executes synchronously and blocks whole app, even though each and every JS documentation tells that then always runs asynchronously. I've also tried to replace the Promise with this:
Promise.resolve().then(() => {
...my code using arg1 and arg2...
});
but got same result.
The only way I've managed to make then block work asynchronously is by using setTimeout:
const pro = new Promise(resolve => {
setTimeout(resolve, 1);
});
pro.then(() => {
...my code using arg1 and arg2...
})
What can be the reason behind then block working synchronously? I don't want to proceed with using setTimeout, because it is kind of a "dirty" solution, and I think that there should be a way to make then run asynchronously.
Application is NodeJS with Express, written using Typescript.
I need to make part of my method's code asynchronous, so it will execute in a non-blocking manner. For this purpose I've tried to create a "dummy" Promise and put the specified code in then block.
Promises don't really make things asynchronous in and of themselves. What they do is wrap around something that's already asynchronous, and give a convenient way to tell when that thing is done. If you wrap a promise around something synchronous, your code is mostly still synchronous, just with a few details about when the .then callback executes.
even though each and every JS documentation tells that then always runs asynchronously.
By that, they mean that it waits for the current call stack to finish, and then runs the code in the .then callback. The technical term for what it's doing is a "microtask". This delay is done so that the order of operations of your code is the same whether the promise is already in a resolved state, or if some time needs to pass before it resolves.
But if your promise is already resolved (eg, because it's wrapped around synchronous code), the only thing your .then callback will be waiting for is the currently executing call stack. Once the current call stack synchronously finishes, your microtask runs synchronously to completion. The event loop will not be able to progress until you're done.
The only way I've managed to make then block work asynchronously is by using setTimeout
setTimeout will make things asynchronous*, yes. The code will be delayed until the timer goes off. If you want to wrap this in a promise you can, but the promise is not the part that makes it asynchronous, the setTimeout is.
I don't want to proceed with using setTimeout, because it is kind of a "dirty" solution
Ok, but it's the right tool for the job.
* when i say setTimeout makes it asynchronous, i just mean it delays the execution. This is good enough for many cases, but when your code eventually executes, it will tie up the thread until it's done. So if it takes a really long time you may need to write the code so it just does a portion of the work, and then sets another timeout to resume later

Using caolan's async library, when should I use process.nextTick and when should I just invoke the callback?

I've been reading up on the differences, and it's hard to think about it when utilizing a library that helps with async methods.
I'm using https://github.com/caolan/async to write specific async calls. I'm having a hard time understanding the use of process.nextTick within some of these async methods, particularly async series methods, where async methods are basically performed synchronously.
So for example:
async.waterfall([
next => someAsyncMethod(next),
(res, next) => {
if (res === someCondition) {
return anotherAsyncMethod(next);
}
return process.nextTick(next); // vs just calling next()
},
], cb);
I've seen this done in code before. But I have no idea why? Just invoking next instead of process.nextTick gives me the same results?
Is there any reason for using process.nextTick in these scenarios, where there is an async method being controlled in a synchronous manner?
Also, what about in an async like the following?
async.map(someArray, (item, next) => {
if (item === someCondition) {
return anotherAsyncMethod(next);
}
return process.nextTick(next); // vs just calling next()
}, cb);
Thanks!
The code is happening in a SEQUENTIAL manner, not a synchronous manner. It's an important difference.
In your code, the async methods are called one after another, in sequence. HOWEVER, while that code is executing, node.js can still respond to other incoming requests because your code yields control.
Node is single-threaded. So if your code is doing something synchronously, node cannot accept new requests or perform actions until that code is finished. For instance, if you did a synchronous web request, node would stop doing ANYTHING ELSE until that request was finished.
What's really happening is this:
Start async action in background (yield control)
Node is available to handle other stuff
Async action 1 completes. Node starts async action 2 and yields control.
Node can accept other requests/handle other stuff.
Async action 2 completes...
And so on. Process.nextTick() says to node 'Stop dealing with this for a while, and come back once you've handled the other stuff that's waiting on you'. Node goes off and handles whatever that is, then gets back to handling your scheduled request.
In your case, there is nothing else waiting so node just continues where it left off. However, if there WERE other things going on like other incoming HTTP requests, this would not be the case.
Feel free to ask questions.

Single thread synchronous and asynchronous confusion

Assume makeBurger() will take 10 seconds
In synchronous program,
function serveBurger() {
makeBurger();
makeBurger();
console.log("READY") // Assume takes 5 seconds to log.
}
This will take a total of 25 seconds to execute.
So for NodeJs lets say we make an async version of makeBurgerAsync() which also takes 10 seconds.
function serveBurger() {
makeBurgerAsync(function(count) {
});
makeBurgerAsync(function(count) {
});
console.log("READY") // Assume takes 5 seconds to log.
}
Since it is a single thread. I have troubling imagine what is really going on behind the scene.
So for sure when the function run, both async functions will enter event loops and console.log("READY") will get executed straight away.
But while console.log("READY") is executing, no work is really done for both async function right? Since single thread is hogging console.log for 5 seconds.
After console.log is done. CPU will have time to switch between both async so that it can run a bit of each function each time.
So according to this, the function doesn't necessarily result in faster execution, async is probably slower due to switching between event loop? I imagine that, at the end of the day, everything will be spread on a single thread which will be the same thing as synchronous version?
I am probably missing some very big concept so please let me know. Thanks.
EDIT
It makes sense if the asynchronous operations are like query DB etc. Basically nodejs will just say "Hey DB handle this for me while I'll do something else". However, the case I am not understanding is the self-defined callback function within nodejs itself.
EDIT2
function makeBurger() {
var count = 0;
count++; // 1 time
...
count++; // 999999 times
return count;
}
function makeBurgerAsync(callback) {
var count = 0;
count++; // 1 time
...
count++; // 999999 times
callback(count);
}
In node.js, all asynchronous operations accomplish their tasks outside of the node.js Javascript single thread. They either use a native code thread (such as disk I/O in node.js) or they don't use a thread at all (such as event driven networking or timers).
You can't take a synchronous operation written entirely in node.js Javascript and magically make it asynchronous. An asynchronous operation is asynchronous because it calls some function that is implemented in native code and written in a way to actually be asynchronous. So, to make something asynchronous, it has to be specifically written to use lower level operations that are themselves asynchronous with an asynchronous native code implementation.
These out-of-band operations, then communicate with the main node.js Javascript thread via the event queue. When one of these asynchronous operations completes, it adds an event to the Javascript event queue and then when the single node.js thread finishes what it is currently doing, it grabs the next event from the event queue and calls the callback associated with that event.
Thus, you can have multiple asynchronous operations running in parallel. And running 3 operations in parallel will usually have a shorter end-to-end running time than running those same 3 operations in sequence.
Let's examine a real-world async situation rather than your pseudo-code:
function doSomething() {
fs.readFile(fname, function(err, data) {
console.log("file read");
});
setTimeout(function() {
console.log("timer fired");
}, 100);
http.get(someUrl, function(err, response, body) {
console.log("http get finished");
});
console.log("READY");
}
doSomething();
console.log("AFTER");
Here's what happens step-by-step:
fs.readFile() is initiated. Since node.js implements file I/O using a thread pool, this operation is passed off to a thread in node.js and it will run there in a separate thread.
Without waiting for fs.readFile() to finish, setTimeout() is called. This uses a timer sub-system in libuv (the cross platform library that node.js is built on). This is also non-blocking so the timer is registered and then execution continues.
http.get() is called. This will send the desired http request and then immediately return to further execution.
console.log("READY") will run.
The three asynchronous operations will complete in an indeterminate order (whichever one completes it's operation first will be done first). For purposes of this discussion, let's say the setTimeout() finishes first. When it finishes, some internals in node.js will insert an event in the event queue with the timer event and the registered callback. When the node.js main JS thread is done executing any other JS, it will grab the next event from the event queue and call the callback associated with it.
For purposes of this description, let's say that while that timer callback is executing, the fs.readFile() operation finishes. Using it's own thread, it will insert an event in the node.js event queue.
Now the setTimeout() callback finishes. At that point, the JS interpreter checks to see if there are any other events in the event queue. The fs.readfile() event is in the queue so it grabs that and calls the callback associated with that. That callback executes and finishes.
Some time later, the http.get() operation finishes. Internal to node.js, an event is added to the event queue. Since there is nothing else in the event queue and the JS interpreter is not currently executing, that event can immediately be serviced and the callback for the http.get() can get called.
Per the above sequence of events, you would see this in the console:
READY
AFTER
timer fired
file read
http get finished
Keep in mind that the order of the last three lines here is indeterminate (it's just based on unpredictable execution speed) so that precise order here is just an example. If you needed those to be executed in a specific order or needed to know when all three were done, then you would have to add additional code in order to track that.
Since it appears you are trying to make code run faster by making something asynchronous that isn't currently asynchronous, let me repeat. You can't take a synchronous operation written entirely in Javascript and "make it asynchronous". You'd have to rewrite it from scratch to use fundamentally different asynchronous lower level operations or you'd have to pass it off to some other process to execute and then get notified when it was done (using worker processes or external processes or native code plugins or something like that).

nodejs - When to use Asynchronous instead of Synchronous function?

I've read some articles about this stuff. However, I still get stuck in a point. For example, I have two function:
function getDataSync(){
var data = db.query("some query");
return JSON.stringify(data);
}
function getDataAsync(){
return db.query("some query",function(result){
return JSON.stringify(result);
});
}
People said that asynchronous programming is recommended in IO bound. However, I can't see anything different in this case. The Async one seems to be more ugly.
What's wrong with my point?
nodejs is asynchronous by default which mean that it won't execute your statement in order like in other language for example
database.query("SELECT * FROM hugetable", function(rows) {
var result = rows;
});
console.log("Hello World");
In other language, it will wait until the query statement finish execution.
But in nodejs, it will execute the query statement separately and continue execute to log Hello World to the screen.
so when you say
function getDataSync(){
var data = db.query("some query");
return JSON.stringify(data);
}
it will return data before db.query return data
function getDataAsync(){
return db.query("some query",function(result){
return JSON.stringify(result);
});
}
but in node.js way the function that pass as parameter is called callback which mean it will call whenever the getDataAsync() finish its execution
We use callback in nodejs because we don't know when db.query() finishes its execution (as they don't finish execution in order) but when it finishes it will call the callback.
In your first example, the thread will get blocked at this point, until the data is retrieved from the db
db.query("some query");
In the second example, the thread will not get blocked but it will be available to serve more requests.
{
return JSON.stringify(result);
}
This function will be called as soon as the data is available from the db.
That's why node.js is called non-blocking IO which means your thread is never blocked.
Asynchronous is used when some operation blocks the execution. It is not an problem in Multi thread application or server. But NodeJS is single threaded application which should not blocked by single operation. If it is blocked by operation like db.query("some query");, Node.js will wait to finish it.
It is similar to you just stands idle in front of rice cooker until it is cooked. Generally, you will do other activities while rice is cooking. When whistle blows, you can do anything with cooked rice. Similarly NodeJS will sends the asychronous operation to event loop which will intimate us when operation is over. Meanwhile Node.js can do processing other operation like serving other connections.
You said Ugly. Asynchronous does not mean to use only callbacks. You can use Promise, co routine or library async.

NodeJS: process.nextTick vs Instant Callbacking

I write lots of modules which look like this:
function get(index, callback) {
if (cache[index] === null) {
request(index, callback); // Queries database to get data.
} else {
callback(cache[index]);
}
}
Note: it's a bit simplified version of my actual code.
That callback is either called in the same execution or some time later. This means users of the module aren't sure which code is run first.
My observation is that such module reintroduces some problems of the multi-threading which was previously solved by JavaScript engine.
Question: should I use process.nextTick or ensure it's safe for the callback to be called outside the module?
It depends entirely on what you do in the callback function. If you need to be sure the callback hasn't fired yet when get returns, you will need the process.nextTick flow; in many cases you don't care when the callback fires, so you don't need to delay its execution. It is impossible to give a definitive answer that will apply in all situations; it should be safe to always defer the callback to the next tick, but it will probably be a bit less efficient that way, so it is a tradeoff.
The only situation I can think of where you will need to defer the callback for the next tick is if you actually need to set something up for it after the call to get but before the call to callback. This is perhaps a rare situation that also might indicate a need for improvement in the actual control flow; you should not be rely at all on when exactly your callback is called, so whatever environment it uses should already be set up at the point where get is called.
There are situations in event-based control flow (as opposed to callback-based), where you might need to defer the actual event firing. For example:
function doSomething() {
var emitter = new EventEmitter();
cached = findCachedResultSomehow();
if (cached) {
process.nextTick(function() {
emitter.emit('done', cached);
});
} else {
asyncGetResult(function(result) {
emitter.emit('done', result);
});
}
return emitter;
}
In this case, you will need to defer the emit in the case of a cached value, because otherwise the event will be emitted before the caller of doSomething has had the chance to attach a listener. You don't generally have this consideration when using callbacks.
http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony
if you're doing callbacks internally, do whichever is suitable
if you're creating a module used by other people, asynchronous callbacks should always be asynchronous.

Resources