asyncLocalStorage loses context in error middleware? - node.js

I am trying to use asyncLocalStorage.getStore in an errorMiddleware after the application throws an error. I noticed that asyncLocalStorage.getStore was returning the right context right before the throw.
But if I add a try-catch around the throw, asyncLocalStorage.getStore() would return the right context. Wondering if context is loss through the error middleware

Related

Getting UnhandledPromiseRejectionWarning even when catching exceptions

In NodeJS, I have some code like this:
function doSomethingAsync() {
return Promise.reject("error");
}
function main() {
doSomethingAsync().catch();
}
When I run this code, I get an UnhandledPromiseRejectionWarning.
I know that making my calling function async and awaiting doSomethingAsync inside of a try/catch makes the error go away, but in this case, I don't want to add the extra complexity of making the function async and awaiting just to mute an error, so I'd prefer to use catch().
Why doesn't my method of error handling mute the error?
.catch() isn't actually catching anything.
If we look at the docs:
Internally calls Promise.prototype.then on the object upon which it was called, passing the parameters undefined and the received onRejected handler.
specs found here
If we then look at the docs for Promise.then, we find:
onRejected: A Function called if the Promise is rejected. This function has one argument, the rejection reason. If it is not a function, it is internally replaced with a "Thrower" function (it throws an error it received as argument).
So doing .catch() will not actually catch anything and your app will continue throwing an error. You have to pass a function to catch().
Doing this will mute the error:
doSomethingAsync().catch(() => { });
Updating to say that this is actually called out here at the top of the page, but I just missed it.

What does `napi_throw_error` do when called from an asynchronous N-API addon's `napi_async_complete_callback`?

I recently completed making an asynchronous version for all the functions in a pure C API, wrapped with N-API to work with JS/TS as a nodejs addon.
The last problem I had to fix was making sure that C POSIX-style errors (ie, returned integer codes) were transferred correctly to the JS at the end of a worker's execution (with the corresponding string, for which we have both an enum of exceptions, and a list of error messages).
When thrown with napi_throw_error (as I did for the synchronous version of all our calls), within the napi_async_complete_callback, these exceptions were never caught at the JS level (I suppose it was because it was within a different async context; I saw online people having a similar problem with ajax). Instead, I opted to just construct my errors as napi_value types, and return these via napi_reject_deferred. This seemed to have the desired effect, of being caught properly when doing a try { await My_NapiWrapper_XYZ() } catch (ex) { ... }.
So I don't really have a problem to fix, but I AM intrigued. These napi_throw_error thrown errors do probably go somewhere. Though I have no idea where. Where should one look to catch an error thrown with napi_throw_error from a napi_async_complete_callback ? Can you give a code example ?
No, they don't go anywhere. It is a bug that I just opened with them:
https://github.com/nodejs/node/issues/41377
There is a general problem with handling exceptions in asynchronous callbacks. Normally, they cannot be catched and should lead to program termination but Node's developers have decided to try to keep it running when they can.

How to surface error in QueueBase#initialize?

When implementing a custom queue, what is the best way to handle error? The documentation shows how to surface error in load message interceptor, but not how to surface error in QueueBase#intialize.
When load message interceptor returns or throws an ErrorData, cast.framework.events.EventType.ERROR will fire. But when QueueBase#initialize returns or throws an ErrorData (or any instance of Error, really), cast.framework.events.EventType.ERROR does not fire, which makes it impossible to handle those error.

Subclassing Bluebird's OperationalError

I'm promisifying a 3rd party library that doesn't throw typed errors, but instead uses the "err" function callback to notify the caller of the error. In this case, the "error" that the library is reporting is just an anonymous JS object with a few well-defined properties.
Bluebird is wrapping this in an OperationalError, which is great - but it'd be even more handy if I could subclass OperationalError and provide my own well-defined Error type that I could define. For instance LibraryXOperationalError - in order to distinguish the errors from this library, from some other error, in some sort of global express error handling middleware.
Is this possible? I tried to come up with a solution using the "promisifier" concept, but haven't had success.
OperationalError is subclassable just like Error is, you can get a reference from Promise.OperationalError

Should async function never ever throw?

I wrote a library with a number of async functions.
A SYNCHRONOUS helper function throws an error if one of the parameters is plain wrong:
proto.makeParameters= function( filters ){
default:
throw( new Error("Field type unknown: " + fieldObject.type ) );
break;
}
In my async functions, when I use it, I have:
proto.someAsyncFunction = function( cb ){
// Run the query
try {
var parameters = this.makeParameters( filters );
} catch( e ){
return cb( e );
}
}
So:
Is it good practice that asyncfunctions should never ever throw? (Like I did)
Right now, I am catching ALL errors. Shall I e more choosy? Maybe make up an error type and just check for that? If so, what should I do in either case?
Your assumptions on the async code are correct. See this post by Isaac Schlueter himself on the topic:
The pattern in node is that sync methods throw, and async methods pass
the error as the first argument to the callback. If the first
argument to your callback is falsey (usually null or undefined), then
all is well with the world.
http://groups.google.com/forum/#!msg/nodejs/W9UVJCKcJ7Q/rzseRbourCUJ
Is it good practice that async functions should never ever throw? (Like I did)
async functions, of course, will throw exceptions whenever we like it not, simply because of the software imperfection. So throwing custom exception is completely fine but what is important is how to correctly catch them.
The problem is that differently from sync code the stack of the async exception may not be available. So when the exception occurs, it is not always possible to say where to return the control and where is the handler. node.js has two methods of specifying what to do when the exception in asynchronous code occurs: process uncaughtException and domains.
As you see, dealing of the exceptions in async code is tricky so throwing an exception should be considered as a last option. If the function just returns status of the operation it is not an exception.
It seems for me that in the provided code fragment the exception is thrown correctly because it indicates that the method was called improperly and cannot do its job. In other words, the error is permanent. This indicates serious flaw in the application that should be fixed. But if the function cannot create a parameter for some temporary reason that can be fixed without modifying the application, then returning the status is more appropriate choice.

Resources