Why can't I catch an async exception with JavaScript? - javascript

I need catch an async exception but i can´t use async/await.
I´m trying to use promises, but it doesn´t work.
An example:
myAsyncFunction().then(function() {
console.log("EVERYTHING OK");
}).catch(function(error) {
console.log(error);
});
function myAsyncFunction() {
return new Promise(function(resolve, reject) {
externalLibraryFunctionAsyncToApiRequest(); //this function throw error
});
}
I can´t modify the externalLibraryFunctionAsynToApiRequest.
Can I do anything to catch a possible exception?

It's not clear what externalLibraryFunctionAsyncToApiRequest actually does. But, if you don't resolve or reject your Promise then nothing is going to come back regardless of success or failure.
You should do something like this:
myAsyncFunction().then(function() {
console.log("EVERYTHING OK");
}).catch(function(error) {
console.log(error);
});
function myAsyncFunction() {
return new Promise(function(resolve, reject) {
try {
throw 'something happend';
// If no error resolve();
} catch (ex) {
reject(ex);
}
});
}

Related

can't get an expect console output when using async await

function fails4() {
return new Promise((resolve, reject) => {
setTimeout(function () {
reject(new Error());
}, 100);
});
}
async function myFunc4() {
try {
await fails4();
} catch (e) {
console.log(e);
console.log('that failed', e); //<-- this gets called
}
}
async function loadmYScript() {
try {
await myFunc4();
} catch (error) {
console.log(error);
console.log(123);
}
}
loadmYScript();
cant't execute the console.log(123) as I expected can anybody help me with this question very appreciated
You're calling loadmYScript, which in turn calls myFunc4, which in turn calls fails4. This last one (fails4) throws an error. The error is "catch-ed" by myFunc4. Inside this catch block you don't throw any error, there's only a couple of logs, so the result of loadmYScript is a fulfilled promise with undefined value. It is not rejected because myFunc4 doesn't throw the error.
If you throw an error inside the catch block of myFunc4, you will have your 123 logged, and the promise will be rejected.

How to catch a callback error with a try catch?

I have an async function that grabs the contents of a file, like so:
async function getFile (name) {
return new Promise(function (resolve, reject) {
fs.readFile(`./dir/${name}.txt`, 'utf8', function (error, file) {
if (error) reject(error)
else resolve(file)
})
})
}
And I call that function into a console log
getFile('name').then( console.log )
If I make an error, like misspelling the file name, I get this handy error:
(node:17246) UnhandledPromiseRejectionWarning: Unhandled promise
rejection. This error originated either by throwing inside of an async
function without a catch block, or by rejecting a promise which was not
handled with .catch(). (rejection id: 1)
I can fix it by doing this:
getFile('name').then( console.log ).catch( console.log ) but is there a way to deal with the error within the callback? Perhaps a try catch? How would I do that?
You still need to catch errors that are rejected.
I think it's where you call your getFile function from - that needs to be wrapped in a try/catch block
try {
const result = await getFile('name')
} catch(e) {
... You should see rejected errors here
}
Or, I think this would work for your example:
await getFile('name').then( console.log ).catch(e => {...})
Testing this in the Chrome DevTools console:
async function test () {
return new Promise(function(resolve, reject) {
throw 'this is an error';
})
}
And calling it via the following:
await test().catch(e => alert(e))
Shows that this does, in fact, work!
If I understand correctly, you want your function to resolve regardless of whether you got and error or not. If so you can just resolve in either case:
async function getFile (name) {
return new Promise(function (resolve, reject) {
fs.readFile(`./dir/${name}.txt`, 'utf8', function (error, file) {
if (error) resolve(error)
else resolve(file)
})
})
}
Then you'd need to handle the errors outside, e.g.
getFile('name')
.then(getFileOutput => {
if (getFileOutput instanceof Error) {
// we got an error
} else {
// we got a file
}
})
or
const getFileOutput = await getFile('name');
if (getFileOutput instanceof Error) {
// we got an error
} else {
// we got a file
}
Is that what you're looking for?

Unhandled exceptions with async await

I am trying to convert my old callback style functions to async await. However I can't understand how can I catch unhandled exceptions.
For example let's say I have a function
apiCall(input, function(error, result) {
if (error) {
console.log(error);
} else {
console.log(result);
}
});
I converted to Promise
function test1(input) {
return new Promise(function(resolve, reject) {
apiCall(input, function(err, result) {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
}
Then I call it
test1(4)
.then(function(result) {
console.log('Result: ' + result);
})
.catch(function(errorr) {
console.log('My Error: ' + errorr);
});
Even though I try to return error, sometimes this function crashes. Let's say disk error, JSON parsing error etc. Some error that I didn't handle. I can only catch those errors with
process.on('uncaughtException', function(error) {
console.log('uncaughtException' + error);
});
Is there a way for me to catch all kinds of error with async await?
EDIT: Here is the full github repo for you to try
https://github.com/tosbaha/promise
Run node testme.js and see that it crashes and exception handler doesn't run.
The file that may crash is this Any function may crash but I can't foresee every kind of error. That is why I am looking for a solution to catch an error inside this file.
If you run the code in my repo with node testme.js you will get the following error
results[trackingId] = trackingArray.doesntExist.Something;
^
TypeError: Cannot read property 'Something' of undefined
As you see that catch handler doesn't catch the error.
If apiCall can crash without calling the callback (with an error), I assume it throws some error that can be handled outside it with a try... catch block (although I'm not sure, because I don't know the internal code of apiCall).
You can try the following:
function test1(input) {
return new Promise(function(resolve, reject) {
try {
apiCall(input, function(err, result) {
if (err) {
reject(err);
} else {
resolve(result);
}
});
} catch (e) {
// reject the errors not passed to the callback
reject(e);
}
});
}

Handling Js promise rejection

How do you handle an error (eg. "new error" below) that is outside of the promise?
function testError() {
throw new Error("new error") // how to handle this?
var p123 = new Promise(function(resolve, reject) {
resolve(123)
});
return p123
};
testError().catch(err => {
return err; // code doesn't come here
})
.then(ok => {
console.log(ok)
});
If you're not sure whether a function will throw (or return a value) synchronously, you can call it using .then(). This will wrap it so that the result will be handled consistently no matter how it is produced:
function testError() {
throw new Error("new error") // how to handle this?
var p123 = new Promise(function(resolve, reject) {
resolve(123)
});
return p123
};
Promise.resolve()
.then(testError)
.catch(err => {
console.error(err);
return err;
})
.then(ok => {
console.log(ok.message)
});
Since the error doesn't involve the async code, a regular try-catch should do fine here:
try {
testError().catch(err => {
return err; // code doesn't come here
})
.then(ok => {
console.log(ok)
});
}
catch(e) {
//
}
Note that when the async-await pattern finally becomes the native way of resolving promises, the try-catch will also become the native way of handling errors:
try {
var ok = await testError();
console.log(ok)
}
catch(e) {
console.log('e:' +e);
}
As one can easily verify, this one correctly handles both the sync and the async error and is much cleaner than then-catch.
If you can, rewrite your testError function like so
function testError () {
return new Promise(function (resolve, reject) {
throw new Error('new error')
resolve(123)
})
}
testError().then(ok => console.log(ok),
err => console.error(err.message))
Run it once to see it throw the error in console.error
Comment out the throw line to see the promise resolve successfully
Since the error is thrown outside of the promises, you cannot catch it using a promise catch statement.
You can use a try/catch to catch the error instead.
function testError() {
throw new Error("new error") // how to handle this?
var p123 = new Promise(function(resolve, reject) {
resolve(123)
});
return p123
};
try {
testError().then(ok => {
console.log(ok)
});
} catch (err) {
console.log(err.message);
}
You rewrite it, because making a caller check for both exceptions and rejections is an anti-pattern:
function testError() {
return Promise.resolve().then(() => {
throw new Error("new error"); // rejects returned promise
return new Promise(function(resolve) {
resolve(123);
});
});
}
testError().catch(err => console.log("Caught " + err));
This is implicit with async functions; they always return a promise:
async function testError() {
throw new Error("new error"); // rejects implicit promise
return await new Promise(function(resolve) {
resolve(123);
});
}
testError().catch(err => console.log("Caught " + err));

Promises not catching error correctly NodeJS

If I remember correctly Promises are supposed to catch an error when one is thrown at all times so that Promise.catch() can be used to handle that error. I don't recall any exceptions however when I throw an error inside setTimeout() this somehow doesn't work.
Can someone explain why this doesn't work? Or is it simply a bug in NodeJS?
Test code
// This works!
function async() {
return new Promise(function (resolve, reject) {
throw new Error('test');
});
}
async().catch(function() {
console.log('Ok: 1');
});
// This doesn't work..
function async_fail() {
return new Promise(function (resolve, reject) {
setTimeout(function() {
throw new Error('test');
}, 1);
});
}
async_fail().catch(function() {
console.log('Ok: 2');
});
You will never catch an Error that is thrown in setTimeout, because it executes async to the actual execution of the promise function. So the promise itself already finished (without any call to resolve or reject) when the function inside set timeout is called.
If you want the promise to fail based on an error inside setTimeout you will need to catch it manually and call reject:
setTimeout(function() {
try{
throw new Error('test');
}catch(ex){
reject(ex);
}
}, 1);

Categories

Resources