nodejs how to do multiple requests - node.js

i need to know how i can write my request to make multiple delete.
the second thing is how can i put async function on my code.
i want to delete a campus and in the same time dele the builings with the same id campus in the JSON
app.delete('/campuses/:id', (req, res)=> {
const id = req.params.id;
const details = { 'campusid': new ObjectID(id) };
db.db('').collection('buildings').remove(details, (err, result)=> {
if (err) {
res.send({ 'error': 'en error has occured' });
} else {
res.send(result);
}
});
const details2 = { '_id': new ObjectID(id) };
db.db('').collection('campuses').remove(details2, (err, result)=> {
if (err) {
res.send({ 'error': 'en error has occured' });
} else {
res.send(result);
}
}
);
})

You can delete like this.
app.delete('/campuses/:id', async (req, res)=> {
try {
const id = req.params.id;
const details = { 'campusid': new ObjectID(id) };
await db.db('').collection('buildings').remove(details);
const details2 = { '_id': new ObjectID(id) };
await db.db('').collection('campuses').remove();
res.send(result);
} catch(err) {
return res.json({
success: false,
message: 'error'
});
}
})

You could make sequential functions where the first one calls the second one. You could then pass on variables to the seconds function (ie. your campus ID).
It could look something like this:
const Query1 = (res, query) => {
const request = new sql.Request();
request.query(query, (err, result) => {
if (err) {
return res.json({
success: false,
message: 'error'
});
} else if (result.recordset[0]) {
let campusID = result.recordset;
Query2(res, campusID, query = 'SELECT bla bla')
}
})
}
const Query2 = (res, campusID, query) => {
const request = new sql.Request();
request.query(query, (err, result) => {
if (err) {
return res.json({
success: false,
message: 'error'
});
} else {
return res.json({
success: true
});
}
})
}

There are various ways to make async call.
You can use promises.
Async Functions.
Sending response without waiting for other tasks.
If you want to make parallel calls you can use bluebird join function

I like the syntax of async functions better than promises, but I use both depending on the situation.
Here is an example of running functions in order before moving to the next function:
async.waterfall([
function(callback1) {
//Do some work, then callback
if (error) {
callback1(errorGoesHere,null);
} else {
callback1(null,successMessageGoesHere);
}
},
function(callback2) {
//Do some work, then callback
if (error) {
callback2(errorGoesHere,null);
} else {
callback2(null,successMessageGoesHere);
}
}
], function (error, success) {
if (error) {
//show an error
}
//all good return the response, etc.
});
If anything in these functions fail, it automatically call the end function to catch the error.

Related

aws-sdk SNS on NodeJs don't catches error

I try to implement a phone number verification by SMS with aws-sdk SNS and Mongoose,
But when I test it with a wrong phone number, like, some gibberish instead of real phone,
the error goes to the console, but then it won't get caught by catch and just crashes it all.
Here is my code
// requires, etc is above here
const verifyPhone = async (req, res) => {
const { phoneNumber } = req.body;
const { userId } = req.user;
let code = generateCode(6);
const session1 = await mongoose.startSession();
try {
session1.startTransaction();
const newCode = await PhoneCode.create(
[
{
userId,
code,
},
],
{ session: session1 }
);
sns.publish(
{
MessageAttributes: {
"AWS.SNS.SMS.SenderID": {
DataType: "String",
StringValue: "Testing",
},
"AWS.SNS.SMS.SMSType": {
DataType: "String",
StringValue: "Promotional",
},
},
Message: "Your code: " + code,
PhoneNumber: "65f76fguyg",
},
(err, result) => {
if (!err) {
session1.commitTransaction().then(() => {
console.log("transaction committed");
res.status(200).json({ message: "SMS sent", result });
});
} else {
console.log(err);
throw new Error(err);
}
}
);
} catch (e) {
await session1.abortTransaction();
res.status(500).json({ message: "Something went wrong!", e });
} finally {
session1.endSession();
}
};
module.exports = verifyPhone;
I suspect that the issue is in throwing the error from inside of sns.publish 's callback, but I don't understand, how else I could do that
Also, if I enter right phone number, the SMS gets delivered, I get the response, but then
mongoose crashes, saying
UnhandledPromiseRejectionWarning: MongoTransactionError: Cannot call commitTransaction after calling abortTransaction
I've just got to a solution. The solution for me was to promisify the sns.publish, after that all went like a charm.
const promisifySNS = (args) => {
return new Promise((resolve, reject) => {
sns.publish(args, (err, result) => {
if (err) {
return reject(err);
}
resolve(result);
});
});
};
Funny enough, if you use more generic promisify, for any function
const promisify = (fn, ...args) => {
return new Promise((resolve, reject) => {
fn(...args, (err, result) => {
if (err) {
return reject(err);
}
resolve(result);
});
});
};
await promisify(sns.publish, opts);
that wouldn't work for some reason.

Unable to call the functions in synchronous way using node.js and mongodb

I am trying to call some function in synchronously using node.js but as per my code its not happening. I am explaining my code below.
viewDraggedFileContent = async(req, res) => {
try{
let id = req.params.id;
if(!id) {
responseObj = {
status: 'error',
msg: 'Please send the mongo id to fetch the file content.',
body: {}
};
res.send(responseObj);
}else{
let response = await findOne(id, 'useCaseFile');
console.log('res', response);
if(response['status'] === 0) {
responseObj = {
status: 'error',
msg: `Error occurred`,
body: response['data']
};
res.send(responseObj);
}else{
const resObj = [{
fileData: response.data.fileData,
_id: response['data']['_id']
}]
responseObj = {
status: 'success',
msg: `Fetched data successfully`,
body: resObj
};
res.send(responseObj);
}
}
}catch(error) {
console.log('Error::', error);
}
}
/**
* 1- Method to fetch single record from mongoDB as per _id.
*/
findOne = async (id, collName) => {
try{
let mongoID = new ObjectId(id);
MongoClient.connect(dbUrl, dbOptions).then(function (client) {
let connObj = client.db(dbName);
connObj.collection(collName).findOne({ _id: mongoID }, function (error, doc) {
if (error) {
client.close();
return {
status: 0,
data: error
};
} else {
client.close();
return {
status: 1,
data: doc
};
}
})
})
}catch(error){
console.log('Error while fetching single record::', error);
}
}
Here I am calling findOne function from viewDraggedFileContent function. My objective is once the required data will return from findOne function then console.log('res', response); should execute but as per my code console.log('res', response); is executing before getting response from findOne. I have also used async---await but still its running asynchronously. Here I need after getting response from findOne function then the console message should display.
You can use async/await in the findOne function
async function findOne(id, collName) {
const client = await MongoClient.connect(url, {
useUnifiedTopology: true,
}).catch((err) => {
console.log("Error while connecting to db", err);
});
if (client) {
try {
let mongoID = new ObjectId(id);
let connObj = client.db(dbName);
let doc = await connObj.collection(collName).findOne({ _id: mongoID });
return {
status: 1,
data: doc,
};
} catch (error) {
console.log("Error while fetching single record::", error);
return {
status: 0,
data: error,
};
} finally {
client.close();
}
}
}
I think that your problem here is that you're not returning a promise so the line calling your findOne function doesn't await anything.
Two solutions here :
When you pass a callback to db.collection.findOne function, it doesn't return anything but, if you don't, you can await a result, like this :
const doc = await connObj.collection(collName).findOne({ _id: mongoID })
Then, you can parse your doc and return it.
The other solution if to return a promise in your findOne function and then, send your result with resolve, like this :
findOne = async (id, collName) => {
return new Promise((resolve, reject) => {
try{
let mongoID = new ObjectId(id);
MongoClient.connect(dbUrl, dbOptions).then(function (client) {
let connObj = client.db(dbName);
connObj.collection(collName).findOne({ _id: mongoID }, function (error, doc) {
if (error) {
client.close();
reject(error);
} else {
client.close();
resolve(doc);
}
})
})
}catch(error){
console.log('Error while fetching single record::', error);
}
}
}
Then, you don't anymore need a status and can use then and catch to get your result.

Issue with update in Mongoose

I have wrote a simple Update function. Its working fine for some minutes and then again its not working. Where I am going wrong? Please help me. I use PUT as my method.
code
accept = (req, res) => {
this._model.update({
user: new mongoose.Types.ObjectId(req.params.uid)
}, {
$set: {
status: 'active'
}
}, (err, obj) => {
if (err || !obj) {
res.send(err);
} else {
res.send(obj);
}
});
}
Model
{
"_id":"5d3189a00789e24a23438a0d",
"status":"pending",
"user":ObjectId("5d3189a00789e24a23438a0d"),
"code":"CT-123-345-234-233-423344",
"created_Date":"2019-07-19T09:13:04.297Z",
"updated_Date":"2019-07-19T09:13:04.297Z",
"__v":0
}
Request
api.abc.com/api/accept/5d3189a00789e24a23438a0d
Sometime it is returing values and sometime null.
You can use the following code to ensure the model is tied to a connection. This could be an issue of connection to the database.
const config = require('./config');
console.log('config.database.url', config.database.url);
return mongoose.createConnection(config.database.url, {
useMongoClient: true
})
.then((connection) => {
// associate model with connection
User = connection.model('User', UserSchema);
const user = new User({
email: 'someuser#somedomain.com',
password: 'xxxxx'
});
const prom = user.update();
// Displays: 'promise: Promise { <pending> }'
console.log('promise:', prom);
return prom
.then((result) => {
// Don't see this output
console.log('result:', result);
})
.catch((error) => {
// Don't see this output either
console.log('error:', error);
});
})
.catch((error) => {
console.log(error);
});
I think you need to use promise or async/await, try this
accept = async (req, res) => {
try {
const result = await this._model.update({
user: new mongoose.Types.ObjectId(req.params.uid)
}, {
$set: {
status: 'active'
}
});
return res.send(result);
} catch (e) {
return res.send(e);
}
};

Using node.js 'util' to promisify is returning an error

I'm trying to create a function in a file to return a promis, which I will call form another file. I'm trying to use the 'util.promisify' to wrap the function, but I'm getting an error. Here is the code and the error:
from my 'checkEmail.js':
const Profile = require('../../models/profile');
const util = require('util');
var exports = module.exports = {};
exports.findEmail = util.promisify(checkEmail());
function checkEmail (email) {
Profile.findOne({ 'emails': { $elemMatch: { email_address: email } } }, (err, userEmail) => {
let conclusion = false;
if (err) {
console.log('Error in looking up an existing email');
} else {
if (userEmail) {
console.log('We found an existing owner for email: ' + email);
conclusion = true;
}
}
return conclusion;
})
}
Calling it on 'profile.js':
router.route('/addemail/:id')
// ADD EMAILS
.put(function (req, res) {
Profile.findOne({ 'owner_id': req.params.id }, function (err, profile) {
if (err)
res.send(err);
EmailCheck.findEmail(req.body.email_address).then((data)=>{
console.log('The answer is: ', data);
});
profile.emails.push({
email_type: req.body.email_type,
email_address: req.body.email_address
})
profile.save(function (err) {
if (err)
res.send(err);
res.json(profile);
});
});
});
The error I'm getting is:
Config for: http://localhost:3000
internal/util.js:272
throw new ERR_INVALID_ARG_TYPE('original', 'Function', original);
Any help would be appreciated.
In order to promisify the function that you pass to util.promisify must:
Take a function following the common error-first callback style, i.e.
taking a (err, value) => callback as the last argument, and returns a version that returns promise
So you can either promisify Profile.findOne, or pass a callback as the last argument to checkEmail
function checkEmail (email, callback) {
Profile.findOne({ 'emails': { $elemMatch: { email_address: email } } }, (err, userEmail) => {
let conclusion = false;
if (err)
return callback(new Error('Error in looking up an existing email'));
if (userEmail) {
console.log('We found an existing owner for email: ' + email);
conclusion = true;
}
return callback(null, conclusion);
})
}
And then you should call it like this:
exports.findEmail = util.promisify(checkEmail);
Otherwise you're passing to .promisify the returned value of checkEmail which is not a function following the style commented above.
You have typo, use util.promisify(checkEmail) instead, parentheses are redundant

the variable i is not filled

I have declare the variable first. but if I do console.log(userinsertData) outside looping variable still not fill.
what i should do for solving this problem?
here my code:
var User = require('../models/user');
module.exports = {
myaction: function(req, res, next) {
var data = req.body,
userinsertData = [];
try {
data.forEach(function(item, index) {
var userdata = new User();
userdata.name = item.name;
userdata.age = item.age;
userdata.sex = item.sex;
userdata.save(function(err, data) {
if (err) {
res.send(err)
} else {
userinsertData.push(data);
}
});
})
} catch (e) {
res.json({
message: 'data not valid'
})
}
console.log(userinsertData);
res.json({
message: 'musician created!',
data: userinsertData
});
}
};
you should solve the problem as
async.eachSeries(data, function (info, callback) {
//here process your data and call callback() for next iteration
}, function (err) {
if (err) {
//this will be called after all iterations and in case of error
}else{
console.log('Well done :-!');
//this will be called after all interations successfully
}
});
this problem you are facing is because of asynchronous nature of nodejs and async helps you to introduce blocking.
Don't forget to include async
Use promise
var User = require('../models/user');
module.exports = {
myaction: function(req, res, next) {
var data = req.body,
userinsertData = [];
new Promise(function(resolve, reject) {
data.forEach(function(item, index) {
var userData = new User(item);
userData.save(function(err, data) {
// if error, reject
if(err) return reject(err);
// we have proceed all items in data, resolve it
else if(data.length - 1 === index) return resolve(userinsertData);
// not finished yet, keep proceeding
else userinsertData.push(data);
});
}).then(function(successResult) {
res.json({
message: 'musician created!',
data: successResult
});
}, function(errorResult) {
res.json({
message: 'data not valid'
});
});
}
};
Use callbacks
var User = require('../models/user');
module.exports = {
myaction: function(req, res, next) {
var data = req.body,
userinsertData = [];
function saveUser(callback) {
data.forEach(function(item, index) {
var userData = new User(item);
userData.save(function(err, data) {
// if error, return callback with error
if(err) return callback(err);
// we have proceed all items in data, return data
else if(data.length - 1 === index) callback(null, userinsertData);
// not finished yet, keep proceeding
else userinsertData.push(data);
});
}
saveUser(function(err, users) {
if(err) return res.json({message: 'data not valid'});
res.json({
message: 'musician created!',
data: users
});
});
}
};
This is what async package does internally

Resources