Will recursively calling a function from a callback cause a stack overflow? - javascript

I want to invoke a function after an event gets fired then in the same call back call the function again. This is to create a sort of event listener when the function completes.
You'll know what i'm trying to do when you see the code:
"use strict";
var page = require('webpage').create();
var system = require('system');
function onStdReadLine(callback) {
system.stdin.readLineAsync(function(err, line) {
callback(line);
onStdReadLine(callback);
});
}
onStdReadLine(function(line) {
// do something when the line comes in
system.stdout.writeLine(line);
});
Question:
Could this potentially cause a stack overflow? Is there a way to refactor this code to not be recursive?
Thanks!

Could this potentially cause a stack overflow?
No, it will not cause a stack overflow. An async callback is called when the stack is completely unwound so there is no stack buildup.
Remember how an async operation works. The current thread of Javascript starts the async operation. That async operation is then managed by some other native code. The current thread of Javascript then runs to its completion and finishes (thus clearing the stack).
Some time later, the native code that is running the async operation sees that the operation has completed and posts an event to the Javascript event queue to call the callback for that async operation. When the JS engine is not running anything else, it will then pull that event out of the queue and process it (calling the callback). At the time it calls the callback, it will have an empty stack frame.
There will be an active scope object for the callback function, but in Javascript scopes are completely separate from the stack frame.
The only time this could be a problem is if your callback was ever called synchronously. Then, there would obviously be a stack build-up and the potential for stack overflow. But, as long as the callback is always called asynchronously (which it should be), then there is no issue.
Is there a way to refactor this code to not be recursive?
It is a very useful design pattern in Javascript asynchronous programming to run the next iteration of something from the completion of the previous iteration and calling a function from within it is the usual way to do so. There is no reason to refactor it.

No, this won't cause a stack overflow. When you call an asynchronous function, the original function returns, so it's stack frame is freed. The callback function is called from the event handler, not from the original function.

Related

Does the event loop run on same thread as the JS main thread?

I am trying to understand asynchronous JavaScript but one thing that I'm wondering is, does the event loop run on the main thread? If so, does all synchronous code in Main() have to go through the event loop? (E.g. does console.log("Hello") also have to go through the event loop?)
And is the event loop the only one who is allowed to push functions to call stack?
Yes, the event loop runs on the same thread as your main function.
No, the event loop doesn't start processing messages until your main function returns. console.log() is synchronous (although there may be some asynchronous processes involved in generating the console output, they have nothing to do with the event loop).
There is only one way that a function (or more accurately a function's stack frame) gets onto the call stack -- the function gets called by whatever is currently on the top of the stack. A function gets removed from the call stack when it returns or throws. In a thread, the function at the top of the stack is what's currently running.
The event loop is at the bottom of the stack, or at least it's underneath all JavaScript functions, so it only gets to run when all previously running JavaScript functions have returned or thrown.
Does the event loop run on same thread as the JS main thread?
JavaScript is often called single threaded, because different pieces of JavaScript can't run at the same time. (Although with the introduction of Web Workers, this isn't necessarily true anymore.) Whether you call this the "main" thread depends on your definition of "main". If you are asking about whether the event loop itself runs on the same thread as the messages it executes, than that would make sense, but this is implementation dependent.
JavaScript doesn't dictate any threading at all. It makes sense for implementations to use only a one thread for the event loop and the JavaScript execution because all the code will always run sequentially, but this isn't a requirement.
As for your questions about event loop and the call stack, you first need to understand how those two work.
The event loop is a simple mechanism that executes queued messages in order and if none are available, it will wait until a new one comes in. A message can be anything that isn't executed immediately. Such as (but not limited to) incoming events (such as clicks), responses from AJAX calls or a callback from setTimeout().
The call stack is the stack of function calls. When a function is invoked (directly, so not via the event loop), a new frame is added to the stack that will be executed. Once the function has completed, the frame is removed from the stack and the code of the previous frame will continue from the point it invoked the completed function. Once all functions are complete and the call stack is empty, the event loop will run the next message.
So to answer your remaining questions:
does all synchronous code in Main() have to go through the event loop?
Not directly. The event loop only invokes the message and wait for it to complete. It doesn't interfere with the execution of the message itself.
is the event loop the only one who is allowed to push functions to call stack?
The only time the event loop interacts with the call stack (or the "execution context stack" as the specification calls it), is when it "spins the event loop". In such a case, the call stack is copied for later use, some other task is performed and later the copied call stack is restored so the execution can continue from the point it left off. But this only happens on a handful of occasions.
Generally, frames are added to the call stack when a (synchronous) function is called. The event loop has little to do with that.
You can read more about the event loop on MDN.
Typically Javascript is single threaded,and the event loop doesn't run like code because it is not.
The event loop has one simple job as a mechanism, which is : To monitor the CALL STACK and CALL QUEUE, if the call stack is empty, the EVENT LOOP takes the first event from the QUEUE and will push it to the CALL STACK, which effectively runs it.
I hope this makes you see the EVENT LOOP from a different perspective.

How much further does code execute after an asynchronous function is called

Apologies if the title of this question is slightly confusing, I was struggling to find a way to word this.
Basically, when an asynchronous function is called, how much further down the code will be executed if the asynchronous function is called from other functions, objects, or files. For example:
function func1() {
// async function 1
// async function 2
}
function func2() {
// more code
}
func1();
func2();
Let's say we execute func1() and both the async functions inside of it take a very long time to run. Will we continue on to func2() while the content of func1() is still being run, or will we block until func1() is finished before continuing to func2()?
JavaScript is single threaded, non-blocking and asynchronous language. JavaScript has call stack, event loop and a callback queue. Words are taken directly from this video. Javascript works on v8 engine (chrome), spider monkey (firefox) which provide JavaScript call stack and heap. v8 or spider monkey provide call stack to Javascript so whenever a function is called, it is stored in the call stack of the runtime (browser in our case, local if you have node installed). Browser also provide the web apis to the javascript like setTimeOut, XMLHttpRequest and DOM. The pictorial illustration is something like this. (Source is the same video which I've tagged.)
JavaScript is single threaded and it means it can execute one function at a time as it has only one call stack. So whenever an asynchronous code (inside func1)is executing, it is executed through webAPIs provided by the browser. The role of callback queues come here. Whenever the result from the Async code is executed, it is stored in the callback queue and it waits for the stack to get empty (event driven programming). Whenever it sees that the stack is empty, the function from the callback queues will start executing.
In your case, you're calling func1, it kicks in some async code but currently func1 is in stack. If the async code has completed and if it sees the stack as empty, it will executed the async code first and then func2 but if the async code hasn't completed, it will start executing the func2 and the callback queue will wait for the stack to get empty. In this case, the flow will be func1 --> func2 --> async code.
So, it is matter of timing. For async code, if the code has returned and waiting in callback queue, as soon as it sees the stack empty, it will kick in and start executing the callbacks (.then or callback from setTimeOut etc.) I'll recommend you to watch that video for better insights and what an event loop in JS is. If I'm missing out something, anyone please feel free to edit this answer or provide suggestions for edit.
JavaScript is single threaded, it literally means nothing can be executed in the same time. If your code has asynchronous nature it means that it is executed in uknown future. I said uknown because it depends from the code. For example asynchronous code for ajax call will be executed when the browser gets the response from the server.
That said, the async code is not executed in the declaration moment but in uknown next event loop. Furthermore it not blocks the current execution. In javascript your execution code can not be disturbed. It just runs through all lines.
Going back to the example, if func1 has no sync blocking code then func2 will be executed right away without any delay.
Asynchronous callback are top level events (similar to button click events) and can only be started when there is no other scripts executing.
Execution will continue till call stack is empty (including "global user code" which what your sample shows) and script engine itself gets control back - so both func1() and func2() will finish before callbacks are executed.
Note: you can't rely on such behavior for normal code - if "asynchronous" function has both synchronous and asynchronous code branches callback from that function can be executed synchronously without even returning to calling function (this can happen with plain callbacks or any other form including promises).

Node.js stacktraces don't include user code

When debugging Node.js code I often encounter call stacks that do not include my program's code in them, only node_modules/non-user code, despite the current line of execution being at a location in my code. This defeats the purpose of following the call stack to see the execution path through my application code.
Why are my source files not showing in the call stack?
It appears that you're looking at an asynchronous stack trace where your code is not in the stack except for your callback because your code unwound/finished and THEN the async callback was called.
All .then() handlers for all promises are called asynchronously with a clean stack. That's per the promise specification. So, promises always let the current thread of execution finish and unwind and then they fire .then() handlers with no user code on the stack when the callback is called. What you are describing is how synchronous code would work, not asynchronous code. We could talk a lot more specifically instead of theoretically if you showed actual code and described where you're looking at the call stack.
Async progress often has to be tracked with logging because you can't easily step through it and you can't just break and look at stack traces either.
As a little simpler example to look at:
function foo() {
setTimeout(() => {
console.log("timer"); // set breakpoint here
}, 100);
}
foo();
The function foo() has finished executing and returned before the callback is called and thus the stack trace will not have any of your code (other than just the callback) on it.
While .then() handlers use a slightly different scheduler than setTimeout(), the principle is the same.

Why do callbacks functions allow us to do things asynchronously in Javascript?

I've read that callbacks make JavaScript asynchronously. But I'm not sure if I understood the explanation. This is what I get
Callback functions allow us to do things asynchronously, since they ensure
that the lines prior to the callback are completely finished before loading
the next line.
Is that true? Thanks
First off, it isn't the callback that enables anything. A given operation in node.js or even browser-based javascript either is or isn't asynchronous. It really has nothing to do with the callback, though a callback is typically used to communicate results of an asynchronous operation.
For example, Javascript's array.forEach() uses a callback, but it is not asynchronous. So, async operations are async because their underlying implementation is non-blocking. You start the operation by making a function call, the operation proceeds in the background and the rest of your code continues to run. Meanwhile, when the asynchronous operation completes, it usually then needs to tell your code that it is done and perhaps communicate some results. A callback function is the chosen mechanism for communicating the completion of the async operation.
I've read that callbacks make JavaScript asynchronously.
No, that is not really true. Callbacks can be used with synchronous operations too. Just because one uses a callback does not make anything asynchronous. The underlying native code implementation of an operation must be asynchronous (such as an Ajax call or other networking operation). Callbacks are used to communicate the results of asynchronous operations. They are also have many other non-asynchronous uses too. So, a callback is just one tool used in an asynchronous operation and a callback is a tool with many other uses too. You cannot say callback === asynchronous.
Callback functions allow us to do things asynchronously, since they
ensure that the lines prior to the callback are completely finished
before loading the next line.
It is hard to tell exactly what you mean by this, but it sounds wrong to me. When using asynchronous operations, code is typically not executed in the order laid out in the file. For example, if you did this:
console.log("async start");
callSomeAsyncOperation(function(result) {
console.log("async done");
});
console.log("I'm here now");
You would see this in the log:
async start
I'm here now
async done
Callbacks and Event Queues Explained
It may also be useful to understand how an asynchronous operation works. Javascript works off an event queue. A given sequence of Javascript code runs to its completion. When that completes, the engine looks in the event queue to see if there are any more events to process. If so, the first event in the queue is pulled out and a callback that was registered for that event is called. This starts a new sequence of Javascript code running. That code continues to run until it finishes. When it finishes, the engine checks for another event. If there is one, it is then processed by calling a callback associated with that event. When there are no more events to process, the engine goes to sleep waiting for the next event. When an event occurs (outside the main Javascript thead), it is then added to the queue and that process of adding it to the queue causes the JS engine to wake up and service that event.
When writing your Javascript, you will often register and event handler for an event. The way this works in Javascript is that you say what event you're interested in (which may also include specifying some other information like what object you're looking for events on) and then you pass it is a function reference. You are, in essence, telling the Javascript engine that you want it to call your function reference when this event occurs. This type of function reference is referred to as a "callback". It's just a normal function, but the context in which it is being used is called a "callback" because some other code will "call you back" at some time in the future by executing your function. You can then place appropriate code in that function reference (inside that callback function) that can respond to that event. Depending upon the type of event, you may only get called once or it may call you every time that event occurs.
You can read more about how this event queue and callbacks work in these references:
Run Arbitrary Code While Waiting For Callback in Node?
blocking code in non-blocking http server
Hidden threads in Javascript/Node that never execute user code: is it possible, and if so could it lead to an arcane possibility for a race condition?
How does JavaScript handle AJAX responses in the background? (written about the browser, but concept is the same)
First of all, let's understand what callback is (by definition):
In computer programming, a callback is a piece of executable code that
is passed as an argument to other code, which is expected to call back
(execute) the argument at some convenient time. The invocation may be
immediate as in a synchronous callback, or it might happen at later
time as in an asynchronous callback. In all cases, the intention is to
specify a function or subroutine as an entity that is, depending on
the language, more or less similar to a variable.
Now, talking about Javascript, not always a callback is asynchronous. For example:
function syncOperation(callback) {
callback();
}
syncOperation(function() {
console.log('a');
console.log('b');
});
console.log('c');
That callback is synchronous, since it doesn't make any asynchronous operation. If you open your console and run the code above, you'll see that it will log a, then b, then c.
Now, let's see an asynchronous example:
function asyncOperation(callback) {
setTimeout(callback, 0);
}
asyncOperation(function() {
console.log('a');
console.log('b');
});
console.log('c');
You'll see firstly c, then a, and b. That's because the setTimeout function runs asynchronously.
Some built-in Javascript functions are asynchronous, and they will run, and at some time, they will call the function you passed as parameter back. That's why if you do:
var a = 'text';
setTimeout(function() { a = 'new text'; }, 0);
console.log(a);
You'll see in your console text, because it will run before the variable has been changed.

Are JavaScript functions asynchronous?

Consider the following function being executed,
function loadPage()
{
takeInput();
processInput();
outputInput();
}
In what order would they be executed(I have read that it follows stack so option 2 will be the answer)?
Option #1
takeInput();
processInput();
outputInput();
Option #2
outputInput();
processInput();
takeInput();
JavaScript functions are not asynchronous. Some very limited set of functions have an asynchronous API:
addEventListener, setTimeout, setInterval. These are the only 3 (which I thought was very surprising).
They allow you to pass in a callback that may get called eventually. Such as when a timer expires, or when a user clicks on something, or when an AJAX request completes.
JavaScript has an event loop. The event loop processes each event as it comes in. If you click a button 3 times and then a timer expires that will also be the order the events are handled. It is all very well defined and determined.
Furthermore, JavaScript doesn't have threads, it runs one event completely till there is nothing left to do (you return) before starting the next event. So events will never interfere in any way. This allows you to make very strong assumptions about the state of your data.
Are JavaScript functions asynchronous?
Some are, most are not.
In what order would they be executed
They will be executed in the order in which they are called. Since they are are all called from the same function, that will be in a simple linear order.
If any of them are written in an asynchronous way, then they might not finish all their activity in the same order. For example:
function a() {
console.log('a');
}
function b() {
console.log('b');
}
function c() {
console.log('c');
}
function aAsync() {
setTimeout(a, 500);
}
function load() {
aAsync();
b();
c();
}
load();
Javascript is not Asynchronous. It works Synchronously ,that is it runs one line of code at a time.
When javascript code is run , first a Global execution context is created and if you call a function from global execution context, another execution context is created by the javascript engine and that is placed at the top of the execution stack (global execution context is already in the stack)and if there is another function being called from inside that function ,another execution context is created and stack size keeps on increasing.
So,javascript engine keeps running this code one line at a time and in that process if there is any event/ http request fires, the browser puts them in the EVENT QUEUE. So, the point is javascript engine wont process the events in queue until the execution stack is empty.
And when the engine is done with the execution stack, it periodically looks if there is any event handler for current event in queue and similarly creates execution context for that handler and runs the code within.
So, the whole process is just synchronous and asynchronousity is just handled by the other parts of browser like(rendering engine or http engine) while the javascript engine continues to run the code synchronously.
So, in your case,
from whichever context function loadpage was invoked , its execution context was created and and placed at the top of the stack. Then, it invokes the takeinput function, its exec. context is created and and other functions context will not be created and placed in the stack until the takeinput context is popped out from the execution stack.
So, the correct order will be takeinput, processinput and outputinput.
I hope it answers your question.
JavaScript is not, generally asynchronous, but it does have asynchronous and event driven methods.
Ajax calls are the big asynchronous methods.
For events, I'm not sure that you can be guaranteed about an order of execution, but I might be wrong about that.
No, not by default/as standard, though there are asynchronous methods. And jQuery makes use of asynchronous behaviour much more so. But in each case, it's subjective, and can't be said that "All of the JavaScript is this or that".
Methods are always executed in the order they are called; the asynchronousness of them means that any may complete before another, even if called afterwards.
Javascript is a single-threaded beast, so strictly speaking tasks are not asynchronous as one might think of in terms of spawning child threads to execute code. The mechanisms that provide this create the illusion of asynchronicity, but its still single-threaded.

Categories

Resources