How can I catch Exception using co module on Node.js? - javascript

I am coding using co module on sail framework.
I want to catch InvalidError but error log says 'undefined'.
How can I fix this code?
Co module can't catch ErrorType specification??
detail: function (req, res) {
co(function *() {
let errors = [];
const text = req.param('text');
if (text.length <= 0) {
throw new InvalidError('text is required');
}
}).catch((InvalidError, err) => {
sails.log.warn(err);
errors.push(err.message);
req.flash('errors', errors);
res.redirect('/somewhere/view');
}).catch((Error, err) => {
sails.log.error(err);
res.serverError(err);
});
}
error log is here
warn: undefined
error: undefined
error: Sending empty 500 ("Server Error") response

The catch method only takes a single argument: err. Try:
.catch(err => {
sails.log.warn(err);
errors.push(err.message);
req.flash('errors', errors);
res.redirect('/somewhere/view');
})

You're not useing Bluebird, are you? The standard catch method does not have error type filtering, you'll need to do that yourself:
.catch(err => {
if (err instanceof InvalidError) {
sails.log.warn(err);
errors.push(err.message);
req.flash('errors', errors);
res.redirect('/somewhere/view');
} else if (err instanceof Error) {
sails.log.error(err);
res.serverError(err);
} else {
console.error("You've thrown a non-error! Shame on you!");
}
});

Related

The URL constructor is not returning a TypeError when passed an invalid URL

Environment
Node v19.0.0
Applied #babel/preset-typescript
Applied #babel/preset-env
tsconfig.json target set to ES6
Background
The below code has a try/catch block where if the new URL constructor fails, I catch the error and handle it using if (err instanceof TypeError)....
Issue
The problem I'm facing is that I have been unable to get err instanceof TypeError to ever be true.
I have tested in my browser that invalid urls passed to URL() throw TypeErrors.
Here are some other observations from console.logging my node environment:
err instanceof Error => false
err instanceof TypeError => false
console.log(err.name) => TypeError
console.log(err.message) => Invalid URL
console.log(err.constructor) => [Functn: TypeError]
function getURLsFromHTML(htmlBody: string, baseURL: string) {
const urls: string[] = []
const dom = new JSDOM(htmlBody)
const linkElements = dom.window.document.querySelectorAll("a")
for (const link of linkElements) {
if (link.href.slice(0, 1) === "/") {
// relative URL
try {
const url = new URL(`${baseURL}${link.href}`)
urls.push(url.href)
}
catch (err) {
if (err instanceof TypeError) {
console.log("Err with relative url", err.message)
}
else {
console.log("Else is logged")
}
}
}
else {
// absolute
try {
const url = new URL(`${link.href}`)
urls.push(url.href)
}
catch (err) {
if (err instanceof TypeError) {
console.log("Err with absolute url", err.message)
}
else {
console.log("Could not find type of err")
}
}
}
}
return urls
}
Why is err not typed as a TypeError, when the only possible failure in the try/catch block is TypeError?

How to throw an Error inside pg pool query in Express JS?

I am facing trouble when I try to throw an Error (to mark if there are no username) inside pool query. What I am expect is the error was catch by checkUsername and make it standard json response. But, I always get an error like this:
Here is my code in controller:
const checkUsername = (req, res) => {
const service = new AuthService()
try {
service.chekcUsernameIsExist(req.body.username, res)
return res.status(200).send('Username is exist')
} catch (error) {
const response = {
status: false,
message: error.message,
error_code: 400
}
return res.status(400).send(response)
}
}
And here is my code in service:
class AuthService {
chekcUsernameIsExist (username) {
const query = `select * from admins where username = '${username}';`
pool.query(query, (err, results, release) => {
if (err) {
throw err
} else if (results.rowCount !== 0) {
console.log('Username is exist')
} else {
console.log('Username is not exist')
throw new Error('Username is not exist')
}
})
}
}
I try to add try catch block inside checkUsernameIsExist but still got the same problem. At the stupid, I add a variable to which have value 1, 2, or 3 to mark is username exist, not exist, or other error.

Cannot set headers after they are sent to the client in node js during updating data

I am new to node.js developement and encountered an error.
First of all here the code inside controller.js.
exports.updateCar = async (req, res,next) => {
const {name} = req.fields
try {
await updateCarService(name,next, (data) =>{
if(data == null || data){
res.status(201).json({
status:true,
message:'updated',
data
});
return
}
})
next()
} catch(e) {
res.sendStatus(500) && next(e)
}
};
and here the method inside services.js.
function updateCars(existingCar,callback){
Car.find({name : existingCar.name}, function (err, docs) {
if (docs.length){
//callback('Car exists already',null);
callback(err,docs)
}else{
existingCar.save(function(err,carr){
console.log('-------',carr)
callback(err,carr);
});
}
});
}
const updateCarService = async (name,next,callback) => {
try{
return await Car.find({name : name},(err,existingCar) => {
if (!err && existingCar.length > 0){
existingCar[0].name = 'audi';
updateCars(existingCar[0],(err2,car) =>{
if (err2 || !car){
console.log('error updated car: ',err2);
}else{
console.log('car updated: ',car);
return callback(car)
}
return
});
}
else if (!err && existingCar.length == 0){
return callback(null)
}
})
}
catch(e){
console.log(error)
}
}
After updating data i get error that :
events.js:187
throw er; // Unhandled 'error' event
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I have tried many possible ways to solve this issue but i couldn't got any solution.
Please help me to resolve this issue.Also if any of style of coding is not good then correct me.

How to test callback of function in Chai?

I am using Slack API and I want to test does it work fine with response status code. Here is sending function :
sendMsg(msg) {
return this.slack.webhook({text: msg}, (err, res) => {
if (err) {
throw err;
}
console.log(res.statusCode) // = 200
return res.statusCode;
});
}
And my test:
it('Checks connection with Slack', (() => {
let slack = new Slack();
let res = slack.sendMsg('test');
expect(res).to.equal(200);
}));
But ofc. it's giving me request object to slack. I want to wait for response object from slack API. Thanks in advance.
It looks like slack.webhook takes in a callback, which is how you retrieve the status. The problem is that the caller of sendMsg has no way of getting that status.
One way to solve this is to have sendMsg take in a callback:
sendMsg(msg, onStatusReceived) {
this.slack.webhook({text: msg}, (err, res) => {
if (err) {
throw err;
}
console.log(res.statusCode) // = 200
onStatusReceived(res.statusCode);
});
}
Then in your test, use done to end the test when the callback is invoked:
it('Checks connection with Slack', (done) => {
let slack = new Slack();
slack.sendMsg('message', status => {
expect(status).to.equal(200);
done();
});
});
Another way is to have sendMsg wrap slack.webhook in a promise, so the caller can do sendMsg().then(...).
one of the ways I handled a returning callback to test is as follows:
it('receives successful response', async () => {
nock('https://localhost')
.persist()
.log(console.log)
.post(‘/getData’, (unitData, callback) => {
return true;
})
.delayBody(1000)
.reply(200, {statusCode: 'Some Status'});
const getSomeData = await getResponse(unitData, function callBack(unitData, error, data){
expect(data.statusCode).to.be.equal(200);
}) })
getResponse Function (returning callback):
getResponse(unitData, function callBack(unitData, error, data){
try {
return request.post(unitData, function (err, resp) {
if (!err && resp.statusCode === 200) {
if (resp.body.error) {
return callback(obj, JSON.stringify(resp.body.error), null);
}
return callback(obj, null, resp);
} else {
if (err == null) {
err = { statusCode: resp.statusCode, error: 'Error occured.' };
}
return callback(obj, err, null);
}
});
} catch (err) {
return callback(obj, err, null);
}
}

Throw object instead of returning string

How to build an Error object instead of give its a string? https://codesandbox.io/s/pwr973487x
async function getUrl() {
try {
const res = await axios.get('https://httpstat.us/500')
} catch(e) {
const errorObj = {
status: 500,
message: 'Internal server error, something is not defined etc'
}
throw new Error('err') //how to build object?
}
}
I want throw Error() to return errorObj. Do I have to do my own class to do that or I can modify the existing Error class for that? I need that so it standardize my error message of my different set of Apis.
You can use the error object returned from catch
try {
const res = await axios.get('https://httpstat.us/500')
} catch(e) {
e.message = 'Internal server error, something is not defined etc';
throw e;
}
You can just add a field to the Error object, e.g.
var err = new Error('Internal Server error');
err.customField = { someProperty: 'some value'};
console.log(err);
And then you can throw it as normal:
throw err;
When you catch the error (higher up in the call stack) you can pull out the custom field:
try
{
throw err;
}
catch (e)
{
console.error(e);
console.log(e.customField);
}
With ES6 onwards you can also create your own error class:
class MyError extends Error {
constructor(message, customValue) {
super(message);
this.field = customValue;
}
get customField() {
return this.field;
}
set customField(obj) {
this.field = obj;
}
};
var ex = new MyError('Error message', {someProperty: 'some value'});
console.dir(ex);
console.log('My custom error details: ', ex.customField);
you could try with the cause propoty of :
TS has inaccurate value type about it at present, this is being discussed on the official to revolve it.
try {
throw new Error('Failed in some way', {
cause: {status: 400}
});
} catch(e) {
console.log(e); // Error('Failed in some way')
console.log(e.cause) // {status: 400}
}
or throw the Error instance with the custom property
try {
const error = new Error('Failed in some way');
error.status = 400;
throw error;
} catch(e) {
console.log(e); // Error('Failed in some way')
console.log(e.status) // 400
}

Categories