Node JS premature program end - javascript

I call a function that stacks two async calls and calls a callback when they have both completed. I am using a really simple method to keep track of the calls that have not completed lock++lock--The problem is that the program exits before the operation of the two functions is complete. I noticed this was the problem when I was debugging and gave the process time to complete before it exits. How can I fix this? (At the moment I am at a bit of a loss on how to exactly explain my problem please ask me anything you need to so I can clarify the question)
-----EDIT
With the script below why when I run it does it just exit? I thought that by calling on I was registering to the event que and the script should continue to run?
var events = require('events');
var eventEmitter = new events.EventEmitter();
eventEmitter.on('spo',function(){
console.log('spo');
});

The problem is that you setup an event emitter and attach a handler to the "spo" event and then you do nothing else. So the node runtime sees that there is nothing left to do and exits. Try this:
eventEmitter.on('spo', function() {
console.log('OK: got event "spo"');
});
eventEmitter.emit('spo');

COMING From a Git Hub thread.
What keeps the event loop alive is handles (sockets, timers, etc.) of which your script has none.
EventEmitter instances are synchronous - that is, they run immediately
- so in your example, once the event has fired, the script is done.
Think of it like this: an EventEmitter in itself isn't useful, it only
becomes useful when it's tied to something that emits interesting
events (data from the network or the file system, a timer that
expires, etc.).
I think that what they are saying is that it is the handle outside of Node into C land that holds the script open.

Related

How many JS statements get processed per event loop?

Is there a set number of instructions statements that get processed before checking the event queue/per tick/per loop (ways of saying the same thing, I think?)
Is there a set number of instructions that get processed before checking the event queue/per tick/per loop (ways of saying the same thing, I think?)
No, there is not.
In the node.js architecture, when an event is pulled from the event queue, it's tied to a callback. The interpreter calls that callback and that callback runs to completion. Only when it returns and the stack is again empty does it check to see if there is another event in the event queue to run.
So, it has absolutely nothing to do with a number of instructions. node.js runs your Javascript as single-threaded so there is no time slicing between pieces of Javascript which it sounds like your question perhaps was anticipating. Once a callback is called that corresponds to an even in the event queue, that callback runs until it finishes and returns control back to the interpreter.
So, it goes like this:
Pull event from the event queue
Call the Javascript callback associated with that event
Javascript callback runs until completion and then returns from the callback
node.js internals check event queue for next event. If an event is there, go to step 1 and repeat
If no event is there, go to sleep until an event is placed into the event queue.
In reality, this is a bit of a simplification because there are several different types of event queues with a priority order for which one gets to go first, but this describes the general process as it relates to your question.
There is no set number of instructions that get processed before checking the event queue. Each message is run to completion. From the Mozilla documentation (https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop):
Each message is processed completely before any other message is processed. This offers some nice properties when reasoning about your program, including the fact that whenever a function runs, it cannot be pre-empted and will run entirely before any other code runs (and can modify data the function manipulates). This differs from C, for instance, where if a function runs in a thread, it may be stopped at any point by the runtime system to run some other code in another thread.
A downside of this model is that if a message takes too long to complete, the web application is unable to process user interactions like click or scroll. The browser mitigates this with the "a script is taking too long to run" dialog. A good practice to follow is to make message processing short and if possible cut down one message into several messages.

Javascript internals - clearTimeout just before it fires

Let's say I do this:
var timer = setTimeout(function() {
console.log("will this happen?");
}, 5000);
And then after just less than 5 seconds, another callback (from a network event in NodeJS for example) fires and clears it:
clearTimeout(timer);
Is there any possibility that the callback from the setTimeout call is already in the queue to be executed at this point, and if so will the clearTimeout be in time to stop it?
To clarify, I am talking about a situation where the setTimeout time actually expires and the interpreter starts the process of executing it, but the other callback is currently running so the message is added to the queue. It seems like one of those race condition type things that would be easy to not account for.
Even though Node is single thread, the race condition the question describes is possible.
It can happen because timers are triggered by native code (in lib_uv).
On top of that, Node groups timers with the same timeout value. As a result, if you schedule two timers with the same timeout within the same ms, they will be added to the event queue at once.
But rest assured node internally solves that for you. Quoting code from node 0.12.0:
timer.js > clearTimeout
exports.clearTimeout = function(timer) {
if (timer && (timer[kOnTimeout] || timer._onTimeout)) {
timer[kOnTimeout] = timer._onTimeout = null;
// ...
}
}
On clearing a timeout, Node internally removes the reference to the callback function. So even if the race condition happens, it can do no harm, because those timers will be skipped:
listOnTimeout
if (!first._onTimeout) continue;
Node.js executes in a single thread.
So there cannot be any race conditions and you can reliably cancel the timeout before it triggers.
See also a related discussion (in browsers).
I am talking about a situation where the setTimeout time actually expires and the interpreter starts the process of executing it
Without having looked at Node.js internals, I don't think this is possible. Everything is single-threaded, so the interpreter cannot be "in the process" of doing anything while your code is running.
Your code has to return control before the timeout can be triggered. If you put an infinite loop in your code, the whole system hangs. This is all "cooperative multitasking".
This behavior is defined in the HTML Standard, the fired task starts with:
If the entry for handle in the list of active timers has been cleared, then abort these steps.
Therefore even if the task has been queued already, it'll be aborted.
Whether this applies to Node.js, however, is debatable, as the documentation just states:
The timer functions within Node.js implement a similar API as the timers API provided by Web Browsers but use a different internal implementation that is built around the Node.js Event Loop.

The mechanics of the JavaScript WebSockets API

I've been trying to understand some code used to open a websocket:
var ws = new WebSocket('ws://my.domain.com');
ws.onopen = function(event) {
...
}
My question is how does the handshaking get started? If it is started in the WebSocket constructor, then how does onopen get called if it isn't set by then? If the WebSocket constructor creates a thread that does the handshaking, then does onopen have to be defined quickly enough before the handshaking is over? If so, that sounds a little dangerous because if the JS virtual machine is slowed the handshaking could be finished before onopen is defined, which means that the event is not handled. Or does setting the onopen function trigger the handshaking?
Could someone explain to me the mechanics of the API please?
It does not look for onopen function until end of execution of current (synchronous) code. That is because the connection (and thus calling onopen callback) is asynchronous.
Consider:
let x = false;
setTimeout(function () {
x = true
}, 1000);
while(!x){
console.log('waiting!');
}
The while loop there will never end but you would probably suspect it'd end after one second.
If you delay the initialisation of onopen function by executing time-consuming (but synchronous) code then it is not dangerous. On the other if you setTimeout initialisation of onopen then there's no guarantee whether it's defined or not at the time the WebSockets connection is ready as you can't be sure which callback will be executed first.
If you were doing the same thing in C++ you'd use threads for that. In JavaScript callbacks mechanism is not thread-based; it just behaves thread-like (see the endless while loop above).
Single thread executes one code-unit at a time and other code units
are queued until the current code unit is finished executing
source: http://www.slideshare.net/clutchski/writing-asynchronous-javascript-101
It's important to understand that even if you setTimeout something for 1s it might not execute after one second - If the thread is busy it might never get executed.
Thus if you initiate WebSocket connection and run a loop similar to the one above but waiting for the connection to be ready it might never end.
This behaviour might look strange for programmers not familiar with JS. Therefore for readability I define callbacks at the same time or immediately after the functions which need them whenever it's possible.
If you want to explicitly use threads and concurrent execution, read more about Web Workers
Reference:
How JavaScript Timers Work
Understanding JavaScript timers
You don't need any setTimeout function. I'm using a library for this and my code looks something like this:
var pushstream = new PushStream({
host: window.location.hostname,
port: window.location.port,
modes: "websocket"
});
pushstream.onmessage = _manageEvent;
function _manageEvent(eventMessage) {
console.log(eventMessage);
}
This gave me a hell of an insight on websockets and how to implement a client in Javascript: https://github.com/wandenberg/nginx-push-stream-module/blob/master/misc/js/pushstream.js
And also the server: https://github.com/wandenberg/nginx-push-stream-module/
It's very well documented I hope it helps :)

Setting JavaScript event handlers after the method call that would trigger the event?

While looking into the IndexedDB API, I have found several examples of event handlers being set after the method call that looks like it should be triggering the event. For example:
var db = null;
try {
var dbOpenRequest = window.indexedDB.open("BookShop1");
dbOpenRequest.onsuccess = function(event){
db = dbOpenRequest.result;
DAO.version = db.version;
...
Although I've done quite a bit of development in JavaScript, I'm embarrassed to say that this looks strange to me. I feel like the event handlers ought to be set before the actual open() call, but I've seen this pattern in several examples. Could someone help me understand this?
Its cause of the single thread and asynchronous nature of JavaScript. When you call open the function is execute immediately. But the onsuccess callback will be put on the function stack of the single thread. These function can not called before the actual function is ended. So you can change the request object in the function and the callback is there when the onsuccess will called. This is nice article to understand the execution context stack.
It appears that opening the database is just an open. It's not an actual DB request and the onsuccess handler is for an actual database request that comes later.
It is good practice to install event handlers before they could possibly be called, but in this case, the dbOpenRequest object doesn't exist until after the open call (it's returned as the result of the open call) so there is no way to put an onsuccess handler on it until after the open. Thus, the onsuccess handler has to be called some time later as a response to some event other than the open (probably a DB query) or never called at all.
It's probably because the open is asynchronous and it has some delay (Opening is not done instantly). JavaScript in the meantime proceeds executing (and binding the events).

Is there a general mechanism to timeout events in node.js?

I am learning node.js and most of examples I can find are dealing with simple examples. I am more interested in building real-world complicated systems and estimating how well event based model of node.js can handle all the use cases of a real application.
One of the common patterns that I want to apply is let blocking execution to time-out if it does not occur within certain timeout time. For example if it takes more than 30 seconds to execute a database query, it might be too much for certain application. Or if it takes more than 10 seconds to read a file.
For me the ideal program flow with timeouts would be similar to the program flow with exceptions. If an event does not occur within certain predefined timeout limit, then the event listener would be cleared from the event loop and a timeout event would be generated instead. This timeout event would have an alternate listener. If the event is handled normally, then both the timeout listener and event listener are cleared from the event loop.
Is there a general mechanism for timeout handling and cleaning up timed out processes? I know some types such as socket have timeout parameter but it is not a general mechanism that applies to all events.
There is nothing like this at the moment (that i know of, but i don't know everything).
The only thing i can think of is that you reset it yourself somehow. I've given an example below but I think it may have some scope issues. Should be solvable though.
var to
function cb() {
clearTimeout(to)
// do stuff
}
function cbcb() {
cb()
}
function cancel() {
cb = function() {} // notice empty
}
fs.doSomethingAsync(file, cbcb)
to = setTimeout(cancel, 10000)

Categories