unable to connect express.js with oracledb - javascript

I am connecting Oracle database using express.js.
oracledb.getConnection(config, function (err, connection) {
if (err) console.log(err);
connection.execute("SELECT * FROM database", function (error, results, fields) {
if (error) {
console.log(error);
res.json({
status: false,
message: "there are some error with query"
})
} else {
if(results !="" && results!= null && results!= undefined){
res.json({
data: results,
status: true,
message: "Data get from db"
})
}
}
})
})
The problem is that when I am running API I got the following error in cmd:
TypeError: Cannot read property 'execute' of undefined'
So after getting this error, I have searched and I got a solution. Then I change my code in the following way:
(async function () {
try {
connection = await oracledb.getConnection({
user: 'xyz',
password: 'xyz',
connectString: 'xyz'
});
result = await connection.execute("SELECT * FROM database");
res.json({
data: result,
status: true,
message: "Data get from db",
length: results.length
})
} catch (err) {
console.error(err.message);
} finally {
if (connection) {
try {
await connection.close(); // Always close connections
} catch (err) {
console.error(err.message);
}
}
}
})();
But after implementing this asynchronous way, I got another errro:
can not locate oracle 64bit client library: "some path.../oci.dll is not the correct architecture"...
UnhandledPromisePejectionWarning: connection is not defined....
UnhandledPromisePejectionWarning: this error is originated either by throwing inside of an async function without a catch, block or by rejecting a promise which was not handled with .catch()
What am I doing wrong?

Related

Rejection because of unhandled promise in Node Js

Hope you are all doing fine!
I am running with some difficulties when I want to deploy this api. I keep on receiving the message:"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(). To terminate the node process on unhandled promise rejection"
My guess is that I am sending a response twice, but I cannot determine where. Does anyone know what could be going on?
router.post('/add', async (req, res) => {
const friend = await User.findOne({username:req.body.friend})
const user = await User.findById(req.body.id)
if(friend && friend != req.headers.username) {
user.friends.find((x) => {
switch(friend.username){
case user.username:{
res.status(401).json({
status: "Failed",
message: "We are sorry but you cant add yourself as friend",
data:null
})
}
case x.friend_username: {
res.status(401).json({
status: "Error",
message: `Sorry, your friend has been already added`,
data: []
})
}
default: {
User.findByIdAndUpdate(req.body.id, {
$addToSet:{
friends: {
friend_id: friend.id,
friend_username: friend.username
}
}
}, {
upsert: true,
safe: true
})
.then(result => {
res.status(200).json({
status: "Success",
message: `Friend has been added correctly! `,
data: result
})
})
.catch((err)=>{
res.status(500).json({
status: "Failed",
message: "Database Error",
data: err
})
})
}
}
})
} else {
res.status(404).json({
status: "Failed",
message: "We are sorry but the username was not found",
data:null
})
console.log(`There has been an failed attempt of adding a new user. \nUser: ${req.headers.username} `)
}
})
`
Try catch block might help with debugging. And it must be used with async/await to catch unhandled promises.
I am assuming that the problem is somewhere within User.findOne() or User.findById(). Ether they are working incorrectly, ether you're passing data in request incorrectly.
router.post('/add', async(req,res)=>{
try {
const friend = await User.findOne({username:req.body.friend})
const user = await User.findById(req.body.id)
if(friend&&friend!=req.headers.username){
user.friends.find((x)=>{
switch(friend.username){
case user.username:{
res.status(401).json({
status: "Failed",
message: "We are sorry but you cant add yourself as friend",
data:null
})
}
case x.friend_username:{
res.status(401).json({
status: "Error",
message: `Sorry, your friend has been already added`,
data: []
})
}
default:{
User.findByIdAndUpdate(req.body.id,{
$addToSet:{friends:{
friend_id:friend.id,
friend_username:friend.username
}}
},{upsert:true,safe:true})
.then(result=>{
res.status(200).json({
status: "Success",
message: `Friend has been added correctly! `,
data: result
})
})
.catch((err)=>{
res.status(500).json({
status: "Failed",
message: "Database Error",
data: err
})
})
}
} }
)}
else{
res.status(404).json({
status: "Failed",
message: "We are sorry but the username was not found",
data:null
})
console.log(`There has been an failed attempt of adding a new user. \nUser: ${req.headers.username} `)
}
} catch(err) {
console.log(err);
}
})
The combination of find() and switch without breaks is probably at the cause, and certainly scrambles the logic.
There are a few other things in the code that can be improved, also. Here's an edit with the changes described in comments...
router.post('/add',async(req,res)=>{
// surround the async calls with try/catch
try {
const friend = await User.findOne({ username:req.body.friend });
const user = await User.findById(req.body.id);
// detect and throw app-level errors. do the express response in the catch
// get the most basic out of the way first. we need a user and a friend for the rest of the route to work
if (!user || !friend) {
throw {
status: 404,
json: {
status: "Failed",
message: "user id or friend name not found",
data: null
}
}
}
// user adding themself as a friend doesn't need a loop to check
if (friend.username === user.username) {
throw {
status: 401,
json: {
status: "Failed",
message: "We are sorry but you cant add yourself as friend",
data:null
}
}
}
// the loop that's needed here is hidden in includes()
if (user.friends.includes(friend.username)) {
throw {
status: 401,
json: {
status: "Error",
message: `Sorry, your friend has been already added`,
data:null
}
}
}
// now, all of the errors have been detected and thrown
// do the upsert with another await and send good status
const addToSet = {
$addToSet:{friends:{
friend_id:friend.id,
friend_username:friend.username
}}
};
// note we await here (not then) since that's the style chosen above
const result = await User.findByIdAndUpdate(req.body.id, addToSet,{ upsert:true, safe:true });
res.status(200).json({
status: "Success",
message: `Friend has been added correctly! `,
data: result
});
} catch (error) {
console.log(error);
res.status(error.status).json(error.json);
}
}

Throwing errors in NodeJS - UnhandledPromiseRejection

I'm pretty new on NodeJS and I'm still trying to figure out how to handle errors. I read a lot of questions but I don't realize what I'm doing wrong.
Here I have a login function:
export const login = async (req, res) => {
let body = req.body;
try {
const user = await User.findOne({ username: body.username });
if (!user) {
throw new InternalError("Username or password are wrong");
}
if (!bcrypt.compareSync(body.password, user.password)) {
throw new InternalError("Username or password are wrong");
}
let token = jwt.sign({ data: user }, "secret", {
expiresIn: 60 * 60 * 24 * 30
});
return res.json({
user: user,
token: token
});
} catch (error) {
throw new GenericError(error);
}
};
And this is the error I get if, for example, I include a wrong password:
(node:12332) UnhandledPromiseRejectionWarning: GenericError: Username or password are wrong
(node:12332) 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()
I know the promises made with Await must have a .then() and .catch() but this is not an error on executing the promise but on validating the password.
What I want is to throw the error and get the response. Right now the request never ends and the previous error is displayed.
Thank you!
PS: InternalError and GenericError are just errors created by me which extends from Error
You receive the warning from node because you are re-throwing a GenericError after catching InternalError. Instead of re-throwing the GenericError, you should return your response or catch your GenericError when calling login.
Here is your code modified for both.
export const login = async (req, res) => {
// We get the body info
let body = req.body;
try {
// We find the user with the username from the body
const user = await User.findOne({ username: body.username });
// Let's assume no user exists, so we throw an InternalError,
// This skips straight to the catch block.
if (!user) {
throw new InternalError("Username or password are wrong");
}
// We never reach these two statements
// because of the error above being thrown.
if (!bcrypt.compareSync(body.password, user.password)) {
throw new InternalError("Username or password are wrong");
}
let token = jwt.sign({ data: user }, "secret", {
expiresIn: 60 * 60 * 24 * 30
});
res.json({
user: user,
token: token
});
} catch (err) {
// We caught our InternalError from not having a user above.
// Now we should return a response that the user is invalid.
// I am just going to return the error that we previously threw.
res.json({
error: err
});
}
};
You can definitely throw the GenericError from your catch block. However, doing that then requires you to catch the GenericError wherever you are calling your login function.
export const login = async (req, res) => {
// We get the body info
let body = req.body;
try {
// We find the user with the username from the body
const user = await User.findOne({ username: body.username });
// Let's assume no user exists, so we throw an InternalError,
// This skips straight to the catch block.
if (!user) {
throw new InternalError("Username or password are wrong");
}
// We never reach these two statements
// because of the error above being thrown.
if (!bcrypt.compareSync(body.password, user.password)) {
throw new InternalError("Username or password are wrong");
}
let token = jwt.sign({ data: user }, "secret", {
expiresIn: 60 * 60 * 24 * 30
});
res.json({
user: user,
token: token
});
} catch (err) {
// Throw the generic error
throw GenericError(err);
}
};
try {
// We call the login function that is defined above.
// It is going to throw a GenericError, so we have to
// catch it.
await login(req, res);
} catch (err) {
// Now we need to catch the generic error
res.json({
error: err
});
}

Chaining more than one promise function in Node.js for mongoDB

There is a requirement, that review can be added only when product and user both are found. So i have written code in order to implement this scenario.
User.findById(req.params.userId).exec()
.then(response => {
console.log("response", response);
if (response) {
return Product.findById(req.params.productId).exec();
}
else {
return res.status(404).json({
message: 'User not found'
})
}
})
.then(response => {
console.log("response", response);
if (!response) {
return res.status(404).json({
message: 'Product not found'
})
}
const review = new Review({
_id: mongoose.Types.ObjectId(),
rev: req.body.rev,
productId: req.params.productId,
userId: req.params.userId
});
return review.save();
})
.then(response => {
console.log("responseeeeeeee", response);
res.status(201).json({
response
})
})
.catch(error => {
console.log("error", error);
res.status(500).json({
error
})
})
This is working fine, but as soon as product or user is missing it is throwing a warning as such :
(node:17276) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at ServerResponse.header (D:\backup-learning\project-shop-always\node_modules\express\lib\response.js:771:10)
at ServerResponse.send (D:\backup-learning\project-shop-always\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (D:\backup-learning\project-shop-always\node_modules\express\lib\response.js:267:15)
at User.findById.exec.then.then.then.catch.error (D:\backup-learning\project-shop-always\api\controllers\review-controller.js:58:29)
at process._tickCallback (internal/process/next_tick.js:68:7)
The problem is that the chain continues with the return value of res.status as the fulfillment value when you do return res.status(/*...*/) from within the then callback.
You can't use a single chain for this. Also, since you need to locate both the user and the product, probably best to do that bit in parallel. See comments:
// *** Start both the product and user search in parallel
Promise.all([
User.findById(req.params.userId).exec(),
Product.findById(req.params.productId).exec()
])
.then(([user, product]) => {
// *** Handle it if either isn't found
if (!user) {
res.status(404).json({
message: 'User not found'
});
} else if (!product) {
res.status(404).json({
message: 'Product not found'
});
} else {
// *** Both found, do the review
const review = new Review({
_id: mongoose.Types.ObjectId(),
rev: req.body.rev,
productId: req.params.productId,
userId: req.params.userId
});
// *** Return the result of the save operation
return review.save()
.then(response => {
console.log("responseeeeeeee", response);
res.status(201).json({
response
});
}
}
// *** Implicit return of `undefined` here fulfills the promise with `undefined`, which is fine
})
.catch(error => {
// *** An error occurred finding the user, the product, or saving the review
console.log("error", error);
res.status(500).json({
error
})
});
If you're doing this in any modern version of Node.js, you can use an async function and await:
// *** In an `async` function
try {
const [user, product] = await Promise.all([
User.findById(req.params.userId).exec(),
Product.findById(req.params.productId).exec()
]);
if (!user) {
res.status(404).json({
message: 'User not found'
});
} else if (!product) {
res.status(404).json({
message: 'Product not found'
});
} else {
// *** Both found, do the review
const review = new Review({
_id: mongoose.Types.ObjectId(),
rev: req.body.rev,
productId: req.params.productId,
userId: req.params.userId
});
const response = await review.save();
console.log("responseeeeeeee", response);
res.status(201).json({
response
});
}
} catch (error) {
console.log("error", error);
res.status(500).json({
error
})
}
Note that the entire code is wrapped in a try/catch, so the async function this is in will never reject (unless the console.log or res.send in the catch block raised errors), so it won't result in an unhandled rejection warning if you just make your Express endpoint handler async (whereas normally passing an async function into something that isn't expecting to receive a promise is an anti-pattern). (If you want to be a bit paranoid, wrap the contents of the catch block in another try/catch.)

How can i handle error with redis and bluebird?

I've been facing with problem with redis and async await.
I have old redis.get with callback:
redis.get(token, async (error, result) => {
if (error) {
return res.status(404).json({ msg: 'Confirm token is invalid.' });
}
if (result === null) {
return res.status(400).json({ msg: 'Confirm token is expired.' });
}
})
But i will want to refactor him to async/await
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
const result = async redis.asyncGet(token)
I successfully get the result, BUT how can i get the error ?
Thanks
Having your code, you just need to surround the redis call using async/await syntax in a try/catch statement:
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
try {
const result = redis.get(token);
} catch (e) {
return res.status(400).send({ msg: 'Confirm token is expired.' })
}

Try/Catch catches promise reject... any way around that?

I have to use try/catch because MongoDb's ObjectId() will break/error if arg is to short.
The promise .catch never fires when the try is good...it seems that the outer catch(e) will catch the promise reject(). Is this expected behavior? anyway around that?
function deleteUser(req, res) {
try {
var userId = { '_id': ObjectId(String(req.params.user_id)) };
var petData = _getAllData(userId);
petData
.then(function(doc) {
data.deleteAllData(doc);
result = user.remove(userId);
_returnApi(result, res);
})
.catch(function(err) {
console.log(`error delete user -${err}`);
res.status(500).json({ error: "error deleting user" });
});
}
catch(e) {
res.status(400).json({ error: "user id format incorrect" });
}
}
Per those two issues 1 and 2 are discussed in Mongoose issue site, after mongoose v4.2.5, the Invalid ObjectId could be caught in find method through exec(), here are the sample codes test under mongoose v4.4.2
Foo.find({_id: 'foo'}) // invalid objectId
.exec()
.then(function(doc) {
console.log(doc);
})
.catch(function(err) {
console.log(err);
})
Output:
{ [CastError: Cast to ObjectId failed for value "foo" at path "_id"]
message: 'Cast to ObjectId failed for value "foo" at path "_id"',
name: 'CastError',
kind: 'ObjectId',
value: 'foo',
path: '_id',
reason: undefined }
However, according to this issue, the update method is still failed.
The way I see it, you can reduce it to single catch block, but return different messages based on the error type then:
function deleteUser(req, res) {
let userId;
return Promise.resolve({ '_id': ObjectId(String(req.params.user_id))})
.then(_userId => {
userId = _userId;
return _getAllData(userId);
}).then(doc => {
data.deleteAllData(doc);
result = user.remove(userId);
return _returnApi(result, res);
}).catch(err => {
if(!userId) return res.status(400).json({ error: "user id format incorrect" });
console.log(`error delete user -${err}`);
res.status(500).json({ error: "error deleting user" });
});
}
}

Categories