NestJS handling UnhandledPromiseRejection with exception filters - node.js

In NestJS the standard approach of handling errors is to let errors propagate up to the exception filter(s) so that code is not littered with try-catch blocks and exception logging and error conversion can be performed in one place.
With the move to node16, an event is thrown when there is no catch on a promise. This change seemingly leads to putting catch statements on all async calls. Is there a better approach that leverage the same exception filters methodology?

Related

Why does NodeJS terminate execution without throwing an exception?

Adding the console.log in this recursive function prevents NodeJS from throwing a "Maximum call stack size exceeded" exception. Instead it just exits after a couple thousand iterations with no message (using Node v16.6.0 on Win10).
Why does the console.log change the exception throwing behavior, and how should I catch this exception without removing the console.log?
(In browsers it also throws an exception as I expected.)
function recursive(i) {
console.log(i)
return recursive(i + 1) * 2
}
try {
recursive(0)
} catch (ex) {
console.log(ex)
}
There is no expected exception here.
Semantically, this is an infinite loop, which is valid. If the JS engine doesn't do tail call optimization infinite recursion (like your example) will cause the call stack to overflow, but this is neither required nor desired. The ECMAScript standard even states how tail calls should be optimized, though this isn't implemented in most JS engines (except for JavaScriptCore used in Safari/WebKit). Whether Node emits the Maximum call stack size exceeded exception or not is nothing you should rely on.

Delphi exception handling, use E: Exception or ExceptObject

We have 2 applications, the first one is VCL project, the other is a windows service.
In the VCL project we do:
try
except
on E: Exception do
// do something with E.Message
end
but in the windows service (which uses several threads) we use:
try
except
// do something with Exception(ExceptObject).Message
end
The information I got from my coworkers is that "We must use ExceptObject in threads and E: Exception in applications that use GUI". But I couldn't find anything regarding this.
I found an example here http://edn.embarcadero.com/article/10452 where it uses an instance variable to store the exception and it uses the ExceptObject, but gives no explanation why.
Is this ExceptObject even thread-safe (since it comes from the unit 'System')?
So what is the right way to handle exceptions in Delphi and why is there more than one way to do it?
There is no right way for exception handling. There is just one way. What might confuse you could be dealing with the exception object which is created, and which causes an exception to raise, but whose lifetime is the most important for you here.
In general, there's only two ways of dealing with those exception objects. Either you let them alive beyond the exception block scope and release them by yourself or let them free by the RTL when the exception block ends.
But to answer what I guess you've asked. Exception class isn't thread safe. And, your coworkers were wrong as no one is forced to use specific exception handling in threads. These rules are the same for all threads created by the process, no matter what. Just, those exception objects can be unstable within exception blocks:
1. Get the current exception object from the ExceptObject
The ExceptObject returns the current exception object. In practice, it may cause this; if you store such object reference into a variable inside an exception handler block and another exception will get raised within such block, that stored instance may become invalid. Which is quite unsafe.
But it doesn't mean you could not take a reference of such object and pass it to another thread by using some synchronization mechanisms (since it's not a thread safe class) and work with it there. You just need to take care that no other exception will be raised because that would invalidate the previously stored object so as you must take care of staying inside the exception handler from the caller's point of view and you must use a kind of thread synchronization mechanism.
So actually working with the exception object acquired from an on expression can be more stable than using ExceptObject. But the same rules applies here as well; you'd need to synchronize the object instance from the on expression with another thread (since it's not a thread safe class), but in such case, object acquired from the on expression won't get changed unlike the ExceptObject one can be within a certain exception block.
2. Retain exception object by using AcquireExceptionObject
The AcquireExceptionObject function allows you to keep the exception object alive even out of the exception block.
For an exception handling when speaking about thread synchronization, I'd suggest you using the AcquireExceptionObject function which makes the exception object free to consume, even after the exception block ends. For you that brings the only responsability, free such acquired object by calling the ReleaseExceptionObject procedure or raising the exception by this object again.
Victoria is absolutely correct.
Personally, I have a strong preference for this idiom:
try
...
except
// IO error
On E : EInOutError do
ShowMessage('IO error : '+E.Message);
// Division by zero
On E : EDivByZero do
ShowMessage('Div by zero error : '+E.Message);
// Catch other errors
else
ShowMessage('Unknown error');
end;
To elaborate:
Victoria said "There is no right way for exception handling. There is just one way." That's absolutely correct.
The advice you got about "use one syntax for threads, and the other for GUIs" is simply wrong. There is no "different syntax" for "threads" vs. "GUI". That's nonsense :(
I prefer using on : MyExceptionType in an exception block.
I also prefer to differentiate different exception types, whenever/wherever possible.
The example you cited, http://edn.embarcadero.com/article/10452, deals with how to avoid a possible access violation if you don't handle the exception within that particular thread. Saving the exception instance in a member variable helps mitigate this problem.
The following link might help clarify:
http://www.delphibasics.co.uk/Article.asp?Name=Exceptions

Force throwTo to block until an exception handler finishes

I'd like to be able to handle an async exception in thread A such that if another thread B calls throwTo, that call blocks until my handler in A has a chance to finish. As I understand it throwTo only blocks until the exception is "received".
I thought maybe some clever use of uninterruptibleMask might help me, but I'm stumped.
EDIT: I just noticed this:
The difference between using try and catch for recovery is that in
catch the handler is inside an implicit block (see "Asynchronous
Exceptions") which is important when catching asynchronous exceptions, ...
I thought that might be suggesting that catch would actually do what I'm looking for (I was using onException), but that doesn't seem to be the case. So as an additional question: what is meant by "the handler is inside an implicit block" here?

When to reject/resolve a promise

I am thinking about when exactly I need to reject a promise.
I found a couple of questions regarding this topic, but could not find a proper answer.
When should I reject a promise?
This article
http://howtonode.org/6666a4b74d7434144cff717c828be2c3953d46e7/promises
says:
Resolve: A successful Promise is 'resolved' which invokes the success listeners that are waiting and remembers the value that was resolved for future success listeners that are attached. Resolution correlates to a returned value.
Reject: When an error condition is encountered, a Promise is 'rejected' which invokes the error listeners that are waiting and remembers the value that was rejected for future error listeners that are attached. Rejection correlates to a thrown exception.
Is this the principle guideline?
That one only reject a promise if an exception occured?
But in case of a function like
findUserByEmail()
I'd would expect the function to return a user, so that I can continue the chain without verifying the result
findUserByEmail()
.then(sendWelcomeBackEmail)
.then(doSomeNiceStuff)
.then(etc..)
What are best / common practises?
In general you can think of rejecting as being analogous to a synchronous throw and fulfilling as being analogous to a synchronous return. You should reject whenever the function is unsuccessful in some way. That could be a timeout, a network error, incorrect input etc. etc.
Rejecting a promise, just like throwing an exception, is useful for control flow. It doesn't have to represent a truly unexpected error; it can represent a problem that you fully anticipate and handle:
function getProfile(email) {
return getProfileOverNetwork(email)
.then(null, function (err) {
//something went wrong getting the profile
if (err.code === 'NonExistantUser') {
return defaultUser;
} else if (profileCached(email)) {
return getProfileFromCache(email);//fall back to cached profile
} else {
throw err;//sometimes we don't have a nice way of handling it
}
})
}
The rejection lets us jump over the normal success behavior until we get to a method that knows how to handle it. As another example, we might have some function that's deeply nested at the bottom of the applications stack, which rejects. This might not be handled until the very top of the stack, where we could log it. The point is that rejections travel up the stack just like exceptions do in synchronous code.
In general, wherever possible, if you are struggling to write some asynchronous code, you should think "what would I write if this were synchronous". It's usually a fairly simple transformation to get from that, to the promised equivalent.
A nice example of where rejected promises might be used is in an exists method:
function exists(filePath) {
return stat(filePath) //where stat gets last updated time etc. of the file
.then(function () { return true; }, function () { return false; })
}
Notice how in this case, the rejection is totally expected and just means the file does not exist. Notice also how it parallels the synchronous function though:
function existsSync(filePath) {
try {
statSync(filePath);
return true;
} catch (ex) {
return false;
}
}
Your Example
Returning to your example:
I would normally chose to reject the promise resulting from findUserByEmail if no user was found. It's something you fully expect to happen sometimes, but it's the exception from the norm, and should probably be handled pretty similarly to all other errors. Similarly if I were writing a synchronous function I would have it throw an exception.
Sometimes it might be useful to just return null instead, but this would depend on your applications logic and is probably not the best way to go.
I know where you're coming from. Q and Q documentation can quite easily have you believe that deferred/promise rejection is all about exception handling.
This is not necessarily the case.
A deferred can be rejected for whatever reason your application requires.
Deferreds/promises are all about handling responses from asynchronous processes, and every asynchronous processes can result in a variety of outcomes - some of which are "successful" and some "unsuccessful". You may choose to reject your deferred - for whatever reason, regardless of whether the outcome was nominally successful or unsuccessful, and without an exception ever having been thrown, either in javascript or in the asynchronous process.
You may also choose to implement a timeout on an asynchronous process, in which case you might choose to reject a deferred without a response (successful or unsuccessful) having been received. In fact, for timeouts, this is what you would typically choose to do.

Node.js error handling guarantee with net.createConnection

I was wondering if Node.js provides any guarantee that the error handler will catch all errors in code like the following:
var c = net.createConnection(port, host);
c.on('error', function (e) { ... });
I've had to deal with code where other statements intervened between the call to createConnection and the statement which sets the error handler, and this sometimes caused errors internal to createConnection to percolate to the top level (presumably because these errors sometimes occurred before the error handler had been set). But unless I'm missing something, this could in principle happen in the code above -- it's just not very likely. Is there any way of actually guaranteeing that all errors which occur within createConnection will get passed to the error handler?
It will only happen if there are bugs in node.
JavaScript is single threaded, the process will not normally be interrupted between attaching the event handler and creating the connection.
No error generated in javascript land will be uncaught by that code.
So if there was a bug in node, there could probably be some errors your code would not catch. If you had some dodgy low level code running in the background causing mayhem it could be possible that some errors would occur that your code would not catch.
But under normal usage, your code is "threadsafe". Your binding the event handler before any errors occur because your code is blocking and nothing can throw errors.

Resources