I'm using bluebird promise with Node.js, after a long piece of code Promise caught an error and when I tried to print out the error message, all it said was:
[ReferenceError: i is not defined]
Is there anything I can do to get more details of the error, like the number of line that made this happen?
While using Promise, I tend to catch error like so:
return User.findOne({
id: someId
}).then(function(foundUser) {
// do something
}).catch(function(err) {
console.log(err);
});
If I just remove the catch mechanism, Node.js will print out all the error stack trace for me...
Related
if I just throw a random error, my code works fine:
throw new Error('you got error')
but if I want to throw it from within a .catch statement, like so:
message.react(e).catch(()=>{throw new Error('you got error')});
Then I get the error gets logged like so: (node:21609) UnhandledPromiseRejectionWarning: Error: you got error, and doesn't get caught by my higher up error handler:
//errors from within catch() don't reach this
process.on('uncaughtException', function(err){ console.log('error caught', err); });
I don't want to use promises, but unfortunately this is from an lib where i don't have a choice.
How can I throw the exception from within the catch in a way that it's not an Unhandled Promise Rejection?
If you're just trying to log unhandled promise rejections for diagnostic purposes, you can do that with:
process.on('unhandledRejection', (reason, promise) => {
console.log('Unhandled Rejection at:', promise, 'reason:', reason);
// Application specific logging, throwing an error, or other logic here
});
See doc here.
As I have said before, this should not be how you actually handle promise rejections. They should be caught in your own code at a lower level where you have the precise context for the particular operation that created the error. This code should be for diagnostic debugging only where you then go and fix the actual code that wasn't handling the promise rejection where it is supposed to be handled.
I'm using a 3rd parth library to make an async call in my nodejs backend code. There's an unhandled promise rejection coming from this call which I'm having trouble catching. (It brings down my node app.)
Based on the input passed, it's expected to fail sometimes:
exports.getSomeData = (input) => {
console.log('GETTING DATA...')
return ThirdPartyLib.makeAsyncCall(input).then((result) => {
console.log('SUCCESS');
return result;
},(rejection) => {
console.log('REJECTED');
return {};
}).catch(error => {
console.log('ERROR');
return {};
});
}
But none of the REJECTED/ERROR messages print when it fails. I just see a console message from the lib: Unhandled rejection at: Promise and my app goes down.
Am I missing anything in the way I handle the non-happy path?
Is it possible for the library code to do something that the above WOULDN'T catch?
Is it possible for the library code to do something that the above WOULDN'T catch?
Sure, it just has to create a Promise (e.g. by calling an async function) without chaining it into the promise chain (aka without awaiting it):
async makeAsyncCall(data) {
Promise.reject("Possible");
}
So yes, the library you are using should either await that detached promise or it should attach an error handler to it (and handle / purposely ignore the error). It's not your fault.
Aside from the double rejection handler (which is pointless, just use catch()), your code should just work.
So given that you are seeing that error, this means that the library you are using has a bug.
Say you have a script that looks like
async function main() {
await somethingThatCanFail()
}
main()
Currently to exit with a non-zero code I'm doing
main()
.then(() => console.log('success message and stuff')
.catch(function(err) {
console.error(err)
process.exit(1)
})
because throw new Error(err) is futile inside of a promise. However, this feels kinda hacky, and I'm wondering if there's a more standard way to do this.
process.exit() is exactly how you should end your process if you want to end it. Nothing "hacky" about that at all.
You properly fielded an error, decided you wanted to abort the process because of that error and ended the process in a documented manner. I would consider an uncaught exception a lot more hacky.
You can output to the console anything you want to for diagnostic purposes before exiting if that's what you thought you might be missing from an unhandled exception.
I am writing promise following this style in the doc:
Q.fcall(promisedStep1)
.then(promisedStep2)
.then(promisedStep3)
.then(promisedStep4)
.then(function (value4) {
// Do something with value4
})
.catch(function (error) {
// Handle any error from all above steps
})
.done();
The catch clause will catch any errors including typos.
However, according to nodejs dos:
By the very nature of how throw works in JavaScript, there is almost never any way to safely "pick up where you left off", without leaking references, or creating some other sort of undefined brittle state. The safest way to respond to a thrown error is to shut down the process.
Some kinds of errors would throw out if we are writing code in the callback style, but not in promise style
This is really confusing me. How should I avoid leaking references when writing in promise.
Thanks~
The example shows good promise chain, including using .done() to make sure any unhandled exceptions are thrown from the promise chain to the outside application.
As far as references and error handling: the promise chains only guarantee than an error will be forwarded to the .catch callback. If there is no way to clean up the state when the error is thrown - you are out of luck. For example
Q.fncall(function firstStep() {
var fs = open file reference
foo.bar; // generates ReferenceError
}).then(function somethingElse() {
...
}).catch(function (err) {
// we have caught ReferenceError
// but we cannot clean up open fs reference!
}).done();
We caught the error, but the catch handler cannot close fs reference. This is what it means that even with promises we have to think how to clean up resources in case of an error.
I am trying to use try-catch block in my protractor test, please see the code below:
try {
element(by.id('usernameas')).sendKeys(data);
}
catch(err) {
console.log('error occured');
}
I am deliberately passing wrong locator to check whether it is going in catch block or not, currently it is giving me error NoSuchElementError on command prompt and test execution stops rather than going into catch block.
Please suggest.
The call to element(locator).sendKeys returns a promise which is either resolved or rejected. The promise is part of the test's control flow.
The call to element(locator) itself does not throw an error, it is the promise which is rejected.
If you fail to find an element you actually want your entire test to fail, since the scneario cannot be completed.
To get the error message you can use the promise callbacks, as demonstrated below.
Important note: if you handle the promise failure by yourself your test won't fail, so you should better rethrow it
try {
element(by.id('usernameas')).sendKeys(data).then(function() {
console.log('keys sent successfully');
}, function(err) {
console.error('error sending keys ' + err);
throw err;
});
}
catch(err) {
console.log('error occured');
}
The console output is (trimmed):
error sending keys NoSuchElementError: no such element
(Session info: chrome=31.0.1650.63)
(Driver info: chromedriver=2.8.241075,platform=Windows NT 6.1 S .....
I ran into this problem recently and noticed that you DONT need the try/catch block. In Protractor, you can achieve the try/catch like following:
try { <---------------------------- Traditional TRY/CATCH method
loadWebApp();
login();
openUserPreferences();
changePassword();
} catch (err) {
console.error(
"An error was thrown! " + err);
}
loadWebApp().
then(login).
then(openUserPreferences).
then(changePassword).
then(null, function(err) { <----------------- PROTRACTOR equivalent of try/catch
console.error(
"An error was thrown! " + err);
});
Here's the source where I got this info from: https://code.google.com/p/selenium/wiki/WebDriverJs#Promises
under Value Propagation and Chaining
So again, you don't need to explicitly add a try/catch.
In short, the reason this method works is because a promise can either be RESOLVED or REJECTED and in case of a rejected or failed promise, this line [ then(null, function(err) { ... } ] will act as the CATCH block. Also notice that the then(null, function(err))( is NOT taking any callback but only an errBack; so basically, this is saying we don't care about whether the promise gets resolved, we only care about whether it fails and thus the NULL for callback and the function(error) for the errBack. No need to wrap this in a try/catch then throw the error as suggested above by the accepted answer (#Eitan Peer). Hope this helps someone out there struggling with Protractor as I did.