You have a block of code that throws an exception. You have tried putting it inside a try..catch block but it still does not get caught. You have been told the error is thrown asynchronously, but you are not sure what is exactly going on. You would like to understand why your code doesn't catch it.
What is asynchronous code
Throwing an asynchronous exception means that an exception is thrown from somewhere in an asynchronously executed callback.
Throwing exception asynchronously
The following code reproduces the example.
Here a try.. catch block is used to wrap a call to setImmediate(). It is a function that operates asynchronously and schedules the argument callback to be called in the near future, as soon as other operations have finished. There are no other statements to execute and the control is passed back to one level up — to the Node.js event loop.
While, in this example, you could add another try.. catch block inside the setImmediate() call, in real life you are dealing with 3rd party code where you have no such possibility.
Pseudocode of event loop
The event loop is an infinite while loop that is entered as the last thing when Node.js process is started. Its responsibility is to repeatedly take events and fire any listeners registered for them one at a time.
It can be described by combining two API functions in a while loop.
Here getNextEvent() returns the next event. If there are no events available, it will block until new events occur. The getListeners() function returns an array of listeners that were waiting for the given event.
Run in two passes
Let us take the example and highlight the two parts that are executed at separate times.
Here the purple section is first executed in one pass. After that pass has finished the control is passed one level up. Then after other operations have finished the setImmediate() contract is fulfilled and the green section is executed.
Let us combine this with the event loop pseudocode. We will replace the listener calling in the pseudocode with the actual code that will be executed. The first pass looks like
And the second part, after the "immediately after other operations have finished" event has occurred, looks like
From the second part it can be seen that the original catch block that was intended to be there is not present. When the code is executed asynchronously, the original synchronous catch block is not present. In this case, the exception will propagate all the way up to the Node.js internals and will cause the program to exit prematurely.
Catch block is not there when asynchronous code is executed
Asynchronous exception is uncatchable because the intended catch block is not present when the asynchronous code is executed. Instead, the exception will propagate all the way and terminate the program.