This question already has answers here:
How to deal with dangling promises
(2 answers)
Closed 3 years ago.
Currently I have code such as:
window.onerror = function() {
// Send some debug info about the defective error handling,
// so that it may be fixed
};
To handle otherwise uncaught exceptions. Unfortunately this does not work for an async function. For example, if we call fooasync() below:
async function fooasync() {
throw 'Catch me!';
}
Then the exception (if otherwise uncaught) won't be caught by the window.onerror catch-all...
I've done the requisite searching and have mostly come accross the answer, "it's not possible and anyway, it would be bad and you should catch it explicitly." I agree of course, but what if you have accidentally not wrapped an async function in a try...catch?
As an example of a valid use-case: I use the window.onerror handler to send me a debug email to let me know that something has gone horribly wrong for the person using my whatever. Great, at least I'm aware of the problem: Now I can fix the issue (and even fix the broken error-handling with an explicit try...catch). However, in the case of the async function, I have no way to even become aware of the issue (other than someone complaining that it's not working the way it's supposed to).
Is it possible to catch these async uncaught exceptions?
Similar to onerror, there is onunhandledrejection, which will be triggered if a Promise rejects and no handler is attached to it. Read on on MDN
Related
This question already has answers here:
What is the point of finally in a try catch/except finally statement
(5 answers)
Closed 5 months ago.
Is there any reason to put code in a finally block as opposed to just having code after the try...catch statement. Surely in both cases the code gets run anyway
try {
something();
} catch (error) {
error_handling_with(error);
}
// code here gets executed whether in finally clause or not.
finally_something();
Is there any place where finally is essential after try...catch? I can see it has a use in Promises, just not here.
finally basically runs even if you have an early-return from try-catch or even if you don't handle the error in the try-catch. Here is an example I like:
function myFunction() {
try {
console.log('inside "try"');
return
} finally {
console.log('inside "finally"');
}
console.log("after try-finally");
}
myFunction()
When you run myFunction(), it will print the following:
inside "try"
inside "finally"
Since you returned from try, it didn't execute any instructions after the try-finally block. But, Javascript did execute the finally block.
I think you have received the correct technical answer for this. However, if you are asking for practical usage, one situation is when you want to close a connection in any case. Here is a pseudo-code to explain:
openConnection();
try {
DoSomething();
return;
} catch (anomaly) {
handleAnomaly();
} finally {
closeConnection();
}
See in the above case, you close the connection in every case whether there is a handled exception, un-handled exception or happy flow, your connection will be closed and that too without duplication of code.
Catch/Finally are optional, the only rule is that 1 of them must always exist.
Finally exists so that code can always be run, disregarding whether or not an error was caught or not.
I would argue that in some cases they are added when they're not needed, but it helps readability, in other cases it might just be a habit.
Thies are example codes in MDN web docs to explain the important of finally block and it behaviour.
openMyFile();
try {
// tie up a resource
writeMyFile(theData);
} finally {
closeMyFile(); // always close the resource
}
Accordig to the MDN documentation finally execute no matter what the logic fail or not inside the try block.
In most cases inside a function there are code blocks must execute before workflow end.
Ex: no matter what if file is get opened it must close before exit from workflow.
function doIt() {
try {
return 1;
} finally {
return 2;
}
}
doIt(); // returns 2
In above code whether it should return 1. It will return 2 because it guarantee the execution of code inside finally block.But according to MDN this is a bad implementation.
Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
This question already has answers here:
Try catch block is not catching nested callbacks
(2 answers)
Is it possible to catch exceptions thrown in a JavaScript async callback?
(7 answers)
Closed last year.
I am trying to catch an error caused by an async javascript callback function,
try{
setTimeout(()=>{
throw err
console.log("after throw")
}, 1000)
}catch(e){
console.log("caught");
}
But as many of you may know catch block is never executed, so what exactly is happening here?
I know I can achieve similar thing using promises and async/await,
async foo(){
try{
await setTimeoutPromise(1000);
}catch(e){
alert("caught");
}
}
When you use setTimeout, the callback gets pushed into the event loop (moved out of the JS Engine and into the realm of the runtime/browser) and your foo function exits immedeatly.
After the timeout AND once the stack is empty, the event loop will put the callback onto the stack and run it. That's why the try/catch and the callback are independent of each other. That's also why setTimeout(1000) does not mean in a second but not earlier than and somewhat close to one second.
See What the heck is the event loop anyway? | Philip Roberts | JSConf EU
These are two different things.
The first code won't catch the error, since it happens asynchronously, and try...catch will only catch synchronously thrown exceptions.
The second code will catch the error, because await 'synchronize' the code (makes it look and work like it would've been synchronous), and the error thrown only by await: if you haven't been used it, you would get only a rejected promise (You can't really throw anything from an async function!)
To make the first code working, move the try...catch inside the callback:
setTimeout(()=>{
try{
throw err
}catch(e){
console.log('catched')
}
console.log("after throw")
}, 1000)
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
The newer node js has async await, which are really cool because it makes the code look better.
I was wondering if it's a good idea to make every class method async, even if it doesn't need to return a promise?
In my use case I actually sort of need that because I'm trying to share dependencies between multiple child processes, and I'm using a combination of Proxy and child process communication to achieve this. And obviously I need promises because I need to wait for the processes to respond or send messages.
But does this have any potential side effects, maybe in the long term?
To be more clear, I want to do this solely for the benefit of cool syntax.
const database = CreateProxy('database');
await database.something();
From another process.
versus some code that just requests something from the parent process like
process.send('getSomethingFromDb');
Under the hood both use messaging, but the first one makes it look like it doesn't on the surface
This concept is a subject for Occam's razor. There are no benefits, while there may be disadvantages.
Extra overhead (both CPU and time) is one of the problems. Promises take some time and resources to be resolved. This may take much less than a millisecond, yet a lag can accumulate.
Another problem is that asynchronicity is contagious, once it reaches module scope, async IIFE should be used everywhere - because top-level await isn't supported yet:
module.export = (async () => {
await require('foo');
// await was accidentally dropped
// this results in race condition and incorrect error handling
require('foo');
...
})();
And here's a good example of a disadvantage that complicates error handling:
async function foo() {
throw new Error('foo');
}
async function bar() {
try {
return foo();
} catch (err) {
console.log('caught with bar');
}
}
bar(); // UnhandledPromiseRejectionWarning: Error: foo
Despite control flow looks synchrounous-like in async, errors are handled differently. foo returns rejected promise, and returned values aren't handled with try..catch in async functions. A rejection won't be handled in bar.
This wouldn't happen with regular function:
function foo() {
throw new Error('foo');
}
function bar() {
try {
return foo();
} catch (err) {
console.log('caught with bar');
}
}
bar(); // caught with bar
Things may become more complicated with third-party libraries that were designed to work synchronously.
I was wondering if it's a good idea to make every class method async,
even if it doesn't need to return a promise?
Your code will work, but I would not recommand it for two reason :
Unnecessary memory/cpu usage
It will makes your code hard to understand. Knowing which function is asynchronous or synchronous is important to understand how a system work and what it is doing.
The result of calling an async function will always be a Promise, regardless of if the function implements any asynchronous behavior.
const asyncTest = async () => 3;
console.log(asyncTest()); // logs 'Promise {<resolved>: 3}'
Because of that, you have to always be sure to call such function with await. But that is purely a comfort issue, if even that for you. But also, creating and resolving Promises adds a little bit of time to each function call, so if performance is critical, you should avoid to call async functions in large numbers, if it can be avoided.
My question consist of two parts:
Part 1
According to standard ES6 Promise I see that I forced to use catch block everywhere, but it looks like copy/paste and looks weird.
Example:
I have some class which makes request to backend (lets call it API class).
And I have a few requirements for API class using:
1) I need to make requests in different parts of my application with single request errors processing:
// somewhere...
api.getUser().then(... some logic ...);
// somewhere in another module and in another part of app...
api.getUser().then(... some another logic...);
2) I want so 'then' blocks would work ONLY when 'getUsers' succeeded.
3) I don't want to write catch block everywhere I use api.getUsers()
api.getUser()
// I don't want following
.catch(e => {
showAlert('request failed');
})
So I'm trying to implement single error processing inside of the class for all "users requests"
class API {
getUser() {
let promise = makeRequestToGetUser();
promise.catch(e => {
showAlert('request failed');
});
return promise;
}
}
...but if request fails I still forced to use catch block
api.getUser()
.then(... some logic...)
.catch(() => {}) // <- I forced to write it to avoid of “Uncaught (in promise)” warning
... otherwise I'll get “Uncaught (in promise)” warning in console. So I don't know the way of how to avoid of .catch block everywhere I use api instance.
Seems this comes from throwing error in such code:
// This cause "Uncaught error"
Promise.reject('some value').then(() => {});
May be you can say 'just return in your class "catched" promise'.
class API {
getUser() {
return makeRequestToGetUser().catch(e => {
showAlert('request failed');
return ...
});
}
}
...but this contradict to my #2 requirement.
See this demo: https://stackblitz.com/edit/promises-catch-block-question
So my 1st question is how to implement described logic without writing catch block everywhere I use api call?
Part 2
I checked if the same API class implementation with Q library will get the same result and was surprised because I don't get “Uncaught (in promise)” warning. BTW it is more expectable behavior than behavior of native ES6 Promises.
In this page https://promisesaplus.com/implementations I found that Q library is implementation of Promises/A+ spec. But why does it have different behavior?
Does es6 promise respects Promises/A+ spec?
Can anybody explain why these libraries has different behavior, which one is correct, and how implement mentioned logic in case if "ES6 Promises implementation" is correct?
I see that I forced to use catch block everywhere
No, you don't need to do that. Instead, return the promise created by then to the caller (and to that caller's caller, and...). Handle errors at the uppermost level available (for instance, the event handler that started the call sequence).
If that's still too many catchs for you, you can hook the unhandledrejection event and prevent its default:
window.addEventListener('unhandledrejection', event => {
event.preventDefault();
// You can use `event.reason` here for the rejection reason, and
// `event.promise` for the promise that was rejected
console.log(`Suppressed the rejection '${event.reason.message}'`);
});
Promise.reject(new Error("Something went wrong"));
The browser will trigger that event prior to reporting the unhandled rejection in the console.
Node.js supports this as well, on the process object:
process.on('unhandledRejection', error => {
// `error` is the rejection reason
});
Note that you get the reason directly rather than as a property of an event object.
So I don't know the way of how to avoid of .catch block everywhere I use api instance.
Surely the caller of getUser needs to know it failed? I mean, if the answer to that is really "no, they don't" then the event is the way to go, but really the code using api should look like this:
function useTheAPI() {
return getUser()
.then(user => {
// Do something with user
});
}
(or the async equivalent) so that the code calling useTheAPI knows that an error occurred; again, only the top-level needs to actually handle the error.
Can anybody explain why these libraries has different behavior, which one is correct, and how implement mentioned logic in case if "ES6 Promises implementation" is correct?
Both are correct. Reporting unhandled exceptions entirely in userland (where libraries live) is hard-to-impossible to do such that there aren't false positives. JavaScript engines can do it as part of their garbage collection (e.g.: if nothing has a reference to the promise anymore, and it was rejected, and nothing handled that rejection, issue the warning).
I have a basic understanding of javascript and have been learning how asynchronous functions work in node.js. I've been very confused by callback functions with the parameter error. For example, here's some code:
contact.saveContacts = function(contactArray, done) {
var jsonfile = require('jsonfile')
jsonfile.writeFile('data.json', contactArray, done)
}
Contact.saveContacts(contacts, function(err) {
console.log('success')
}
My question is, why does the callback function contain the parameter error? I'm confused to why it's there because it seems as if it serves no purpose in the function it calls.
This is a pattern called an error first callback and is used a lot in javascript.
See this article for reference.
Typically synchronous functions either return successfully, possibly with a value, or throw an exception if there is a problem. The calling code can choose what to do if an exception is thrown, by either catching and inspecting the error or by letting it fall through to other code that may handle the error.
Asynchronous callback functions are called after the calling code has already executed. This means there's no opportunity to catch thrown exceptions. So instead of throwing, errors are passed through to the callback function so the calling code can handle both success and error states.
in case there is a problem with write operation such as permissions error object is invoked and the reason in this to prevent unexpected errors.
Imagine we are giving a order to do computer starts doing it but on the way theres a block about permissions that computer cannot write into that dir in this case computer doesnt know what to do and our program crashes to prevent this inside callback we specify what to do in such cases for example if permission is denied and the reason is write permission prompt user for password and force writing or open a box to user that user must run this as user
The error parameter has no usage if everything goes fine. But, its too useful when there comes an error. Any type of error e.g. runtime error, of file has been deleted or anything, if happens, the details of the error will be present in the error parameter of the callback. So, its better to use that parameter as following:
Contact.saveContacts(contacts, function(err) {
if(err){
console.log(err);
}
else{
console.log('success');
}
}
In this way, you will get to know any error, if that happens with the function.