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
Related
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.
I'm pretty new to typescript and I faced the issue with extending the Request type. I actually found a solution, but it doesn't feel right to me, and seems like there might be a better way.
First, the structure. I have a middleware checkAuth that checks the Bearer token, finds the user in the database (or creates one, in case it's the first time) and adds user to the req variable.
Most people recommend modifying the Express' Request type with custom declarations. I don't like this idea, because that will put user object into all requests, even before I actually save user into req.
Another solution is what I use now:
interface ReqWithUser extends Request {
user?: {
...
}
}
This allows me to declare req: ReqWithUser. But there's a flaw. When I try to access req.user, typescript is telling me that it's possibly undefined. Well, that's exactly what I declared with user?:. If I don't put a question mark there, then typescript is mad in router, saying Property 'user' is missing in type Request. That's fair. One of the solution is to use req!.user. Solves all problems, but it still feels imperfect to me. I know the req.user is there, it's not optional, otherwise checkAuth would fail and return 401. If it didn't, the user is there. What feels like the right solution is somehow modify the req type after the checkAuth middleware. Because that's when user is added into the req. Is it possible?
The issue has nothing to do with your types, but it's the fact that Express will always emit Request and not RequestWithUser.
So in your middleware function, you will always get a Request. The only reason RequestWithUser is acceptable is because you made it optional.
Truth is the middleware / decorator pattern doesn't work that well with express. You have a few options (some of which you mentioned)
Use declaration merging to 'patch' the built-in Request. You already mentioned you don't like this though, because it's a bit of a hack.
Don't use Express' middleware system and instead write something that understands how types change with decorators. I don't know exactly what this looks like, or if this has been done before.
Whenever you want to use RequestWithUser in your controllers/middlewares start off with an assertion function to ensure that user exists (allowing you to make it non-optional).
Cast to RequestWithUser, when you need it.
All these options have drawbacks:
You don't like for the reasons mentioned. It's not always 'accurate' so you are sort of lying to Typescript for convenience.
Sounds hard to do
Requires the use of an assertion function, which means you need to do a little extra work every time you want to use the user property. This work is not needed because you as developer know.
You probably don't like casting for the same reason you don't like to use declaration merging.
By far I think 2 is the best solution, because it gives you the advantage of typing without any hacks and without having to do the extra work of an assertion function (which happens during runtime). But it means abandoning Express' Middleware system. I wouldn't know exactly how to write this code, but I am curious how if it can be done...
FYI I opened another stack overflow question, because I am curious:
Typescript typing for decorator middleware patterns
I'm using sinon to stub an instance of express-Request.
It looks something like this:
let req = sinon.createStubInstance(Request);
My method accepts req: Request but my IDE complains about me using SinonStubbedInstance<Request> rather than Request.
I've tried using req as Request but I still get a warning about 'may be a mistake' and that I should first cast to unknown and only then to Request.
I actually don't need anything from this parameter so I really just want to stub it quickly and easily.
When using it in the call to your method, just cast it:
myMethod(req as any);
I understand that this was posed 3 years ago, but since the only answer given is wrong, I feel obliged to comment, for someone else might benefit from it.
It's strongly discouraged to use as any and your compiler should complain about this (unless you have a very good reason not to, you should use strict compiler option).
Casting to unknown and then to your type seems unintuitive, but it is a cleaner way than casting to any. If you use any you might be better off not using typescript at all.
https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html#any
Consider doing
let req: SinonStubbedInstance<Request> & Request = sinon.createStubInstance(Request);
instead.
P.S.: Also, the use of let seems suspicious (sure cannot use const?), but that's a different topic.
enter image description here
No idea whats going with these errors code, i dont understand why is it saying anonymous and its giving me security concerns
Strictly speaking, those are warnings (not errors). Nothing is broken, but some things may be running sub-optimally. The alerts are noting that the code on your site is preloading a number of assets but not using them right away. This may indicate that your site is unnecessarily using priority resources to bring those resources in.
Beneath the warning message, you are seeing what is known as a "call stack" - it's the chain of functions that have been called to get to the point that resulted in that warning message. There are two kinds of functions in Javascript: named functions and anonymous functions.
Named functions are what you might normally think of as a function. You declare it with something like:
function doSomething(parameter){
// Some awesome code here
}
And later call it as:
doSomething(some_input);
However, in Javascript we can also create un-named, aka anonymous, functions in-line. This is often done for 'callback' functions, or functions that serve as a part B to the main function's part A, especially when part A does something asynchronously.
For example, if we want to fetch a file and then do something with it once it loads, we would make an asynchronous file call and then run our callback function once it loads. If we're using a library like jQuery as a helper to make that call, our code might look something like this:
function getPageAndDoStuff(url, callback){
jQuery.get(url, callback)
}
// We can declare a named function to do our stuff...
function justLogIt(html){
console.log(html);
}
getPageAndDoStuff('/cart', justLogIt);
Alternatively:
// We can just declare an inline anonymous function to do that
getPageAndDoStuff('/cart', function(html){
console.log(html);
})
The latter is a common design pattern for many types of tasks, but you'll note that the function we pass around doesn't have a name. When something happens and we look at the call stack to see the order of functions that have been called to get us to that point, what name would we print? Each unnamed function in our chain is simply called "(anonymous)"
Going back to your posted image, there is nothing in what you're showing that indicates a cause for serious concern. The script file 'rocket-loader' is possibly pre-loading a few assets that it doesn't need to, so you may be able to boost your site's performance by tweaking whatever parameters 'rocket-loader' uses to be more selective in what you are pre-loading.
When I run my code with node 0.10.26, I'm getting an 'illegal access' error when using ES6 proxies. It doesn't happen with node 0.11.14
Any ideas how I can try to approach this? There's no stack trace.
I have a pretty convoluted proxy implementation, I've implemented the following methods:
get, set, has, hasOwn, delete, keys, enumerate, getOwnPropertyNames, getPropertyNames, getOwnPropertyDescriptor, getPropertyDescriptor
Is there a Proxy test suite set I can throw at it to see if I've implemented something incorrectly? Or any other way to see the source of the problem? I don't even know how to invoke half of the things I implemented :)
Any libraries that I can replace the Proxy object with? I think I saw one before but can't find it now.
EDIT: more details I forgot: It's not that there's no stack track, there's a stack trace from bluebird promise and it begins with Promise$_rejectPromises, which makes me think the error is related to this problem but I still don't know how find the source error with the problematic property.
So while looking for a Proxy replacement, I stumbled onto this thread, which says that this problem happens when something tries to use JSON.stringify() on the proxy.
I'm happy to say that implementing my own toJSON() method on the proxy object solved the problem.
Ahhh... so good to be back to 0.10.26