amqplib nodejs to consume rabbitmq - node.js

this is how i consume the queue in rabbit, i wonder why this promise still hangs and return no result. i am trying to hit an endpoint that call this promise and expect it to return just ok to make sure it gives me a 200 OK status. now it acts like it somehow does not get any return from this service, i wonder what i did wrong. thanks
return new Promise((resolve,reject) => {
try{
rabbit.then(conn => {
return conn.createChannel();
})
.then(ch => {
let shit = ch.assertQueue(USER_LOG_QUEUE)
.then(ok => {
if(ok.messageCount > 0){
return ch.consume(USER_LOG_QUEUE, function(msg) {
if (msg !== null) {
ch.ack(msg);
writeToFile(msg.content.toString())
.then(rs => {
console.log(rs);
})
.catch(err => reject(err));
}
console.log('finished');
ch.close();
resolve(ok);
})
}else{
console.log('empty list : finished');
ch.close();
resolve(ok);
}
})
.then(ok => {
console.log('empty list2 : finished');
resolve(ok)
})
.catch(err => reject(err));
}catch(err){
reject(err);
}
});

Related

My program writes the data to file successfully, but the URL data needs to be checked by my link checker. Node.js

https://github.com/strawberries73/OSD600-Journey-on-rocky-trails
I need the data converted to show URLs only for my Link Check to work. I have tried another solution but the new code solution deletes the conversion before it gets read. If there is a way to pull the URL's and get them to be written to a different file or the same file, my link checker would work.
// ExitCode
process.on("SIGTERM", () => {
server.close(() => {
console.log("Program is terminated");
});
});
//Flag labeling each URL as a good or bad
const _label = ({
good: "GOOD",
bad: "BAD"
});
//const getTelescope = fetch('http:/') data
async function getTelescopeData(){
//fetching data from local host
fetch("http://localhost:3000/posts").then(response => {
return response.json();
}).then(data => {
console.log(data);
//truncate the data and write to file
fs.truncate("telescopeData.txt", 0, function() {
for(i = 0; i < data.length; i++) {
fetch(`http://localhost:3000${data[i].url}`)
.then(res => {
return res.json();
}).then(telescopeData => {
//Append to telescopeData.txt
fs.appendFile("telescopeData.txt", telescopeData.html,
(err) => {
if(err) {
console.log(err)
.then.process(); //Termination
}
});
});
}
});
}
);
}
getTelescopeData(); //Data fetched
if(process.argv.length==2){
greetingMessage();
console.log("Hello");
}
else{
const filePath=path.join(__dirname,process.argv[2]);
fs.readFile(filePath,"utf-8",(err,data)=>{
if(err){
console.log("Fail to read file",err);
}
else{
const validUrl=data.match(/(http|https)(:\/\/)([\w+\-&#`~#$%^*.=/?:]+)/gi);
validUrl.forEach((url)=>{
fetch(url,{method:"HEAD",timeout:2000})
.then((res)=>{
if(res.status==200)
console.log(res.status,url.green,_label.good.rainbow);
else if(res.status==400||res.status==404)
console.log(res.status,url);
else console.log(res.status,url)
.then.process(); //Termination
})
.catch((error)=>{
console.log("404",url.red, _label.bad.bgRed);
});
});
}
});
}
Output of Data in the console
New Code tried, only it deletes the input after it has been written to file.
// ExitCode
process.on("SIGTERM", () => {
server.close(() => {
console.log("Program is terminated");
});
});
//Flag labeling each URL as a good or bad
const _label = ({
good: "GOOD",
bad: "BAD"
});
//const getTelescope = fetch('http:/') data
async function getTelescopeData() {
//fetching data from local host
fetch("http://localhost:3000/posts").then(response => {
return response.json();
}).then(data => {
console.log(data);
//truncate the data and write to file
fs.truncate("telescopeData.txt", 0, function () {
for (i = 0; i < data.length; i++) {
fetch(`http://localhost:3000${data[i].url}`)
.then(res => {
return res.json();
}).then(telescopeData => {
//Append to telescopeData.txt
fs.appendFile("telescopeData.txt", telescopeData.html,
(err) => {
if (err) {
console.log(err)
.then.process(); //Termination
}
});
});
}
});
// its not reading the file for some reason. File is empty when I add this.
fs.readFile("telescopeData.txt", "utf-8", (err, data) => {
if (err) {
console.log("Fail to read file", err);
}
else {
console.log(data);
console.log("^^^");
const validUrl = data.match(/(http|https)(:\/\/)([\w+\-&#`~#$%^*.=/?:]+)/gi);
console.log(validUrl);
console.log("^^^");
validUrl.forEach((url) => {
fetch(url, { method: "HEAD", timeout: 2000 })
.then((res) => {
if (res.status == 200)
console.log(res.status, url.green, _label.good.rainbow);
else if (res.status == 400 || res.status == 404)
console.log(res.status, url);
else console.log(res.status, url)
.then.process(); //Termination
})
.catch((error) => {
console.log("404", url.red, _label.bad.bgRed);
});
});
}
});
} // then ends
);
}
if (process.argv.length == 2) {
greetingMessage();
console.log("Hello");
} else if (process.argv[2] == "--telescope") {
console.log("Telescope");
getTelescopeData();
}
else {
const filePath = path.join(__dirname, process.argv[2]);
fs.readFile(filePath, "utf-8", (err, data) => {
if (err) {
console.log("Fail to read file", err);
}
else {
const validUrl = data.match(/(http|https)(:\/\/)([\w+\-&#`~#$%^*.=/?:]+)/gi);
validUrl.forEach((url) => {
fetch(url, { method: "HEAD", timeout: 2000 })
.then((res) => {
if (res.status == 200)
console.log(res.status, url.green, _label.good.rainbow);
else if (res.status == 400 || res.status == 404)
console.log(res.status, url);
else console.log(res.status, url)
.then.process(); //Termination
})
.catch((error) => {
console.log("404", url.red, _label.bad.bgRed);
});
});
}
});
}
async function getTelescopeData(body, url){
//fetching data from local host
const localRegex= /https?:\/\/localhost:[0-9]*/;
const baseurl=url.match(localRegex);
return JSON.parse(body).map((i)=>{return baseurl[0]+i.url;
})
}

finally() executed before then() completes in prepared statement execution

I am new to node.js and I'm having an issue with connecting to an mssql database and preparing/executing a prepared statement.
I have the following code:
this.connectionPool.connect().then(pool => {
// Create prepared statement
stmt = new mssql.PreparedStatement(pool);
// PREPARE
stmt.prepare(command, err => {
//TODO: check for errors in prepare
// EXECUTE
stmt.execute((err, result) => {
//TODO: check for errors in execute
// UNPREPARE
stmt.unprepare(err => {
//TODO: check for errors in unprepare
});
console.log(`Rows affected: ${stmt.rowsAffected}`);
console.log(`Result: ${result}`);
return result;
});
});
}).catch(err => {
console.log(`Connection pool error: ${err}`);
}).finally(() => {
// Close connection
console.log("Closing connection.");
if (this.connectionPool.connected) {
this.connectionPool.close();
}
});
I'm finding that the finally() promise is executed at the same time as then(), which I wouldn't have expected. This is causing the connection to be closed before the statement can be prepared.
ConnectionError: connection is closed
How can I ensure the connection is closed only after the statement has been executed?
The callbacks are executed async, so you need to add the result of the execute in the promise chain:
this.connectionPool.connect().then(pool => {
// Create prepared statement
stmt = new mssql.PreparedStatement(pool)
// return a promise to add it to the promise chain
return new Promise((resolve, reject) => {
stmt.prepare(command, err => {
// TODO: check for errors in prepare
if (err) {
reject(err)
return
}
// EXECUTE
stmt.execute((err, result) => {
// TODO: check for errors in execute
if (err) {
reject(err)
return
}
// UNPREPARE
stmt.unprepare(err => {
// TODO: check for errors in unprepare
if (err) {
reject(err)
}
})
console.log(`Rows affected: ${stmt.rowsAffected}`)
console.log(`Result: ${result}`)
resolve(result)
})
})
})
}).catch(err => {
console.log(`Connection pool error: ${err}`)
}).finally(() => {
// Close connection
console.log('Closing connection.')
if (this.connectionPool.connected) {
this.connectionPool.close()
}
})
If stmt.prepare support promise out of the box, you may return it without wrapping it in a new Promise
All promise version:
this.connectionPool.connect().then(pool => {
// Create prepared statement
stmt = new mssql.PreparedStatement(pool)
return stmt.prepare(command)
.then(() => stmt.execute())
.then((result) => {
console.log(`Rows affected: ${stmt.rowsAffected}`)
console.log(`Result: ${result}`)
})
.finally(() => stmt.unprepare())
}).catch(err => {
console.log(`Connection pool error: ${err}`)
}).finally(() => {
// Close connection
console.log('Closing connection.')
if (this.connectionPool.connected) {
this.connectionPool.close()
}
})
The .prepare(), .execute() and .unprepare() methods all accept callbacks. Unless these methods are "promisified", the this.connectionPool.connect().then().catch().finally() chain has no means of being informed of the outcome of the prepare-execute-unprepare process.
The prepare-execute-unprepare process can be promisified as follows:
this.connectionPool.connect()
.then(pool => {
let stmt = new mssql.PreparedStatement(pool);
return new Promise((resolve, reject) => {
stmt.prepare(command, err => {
if(err) {
reject(err);
} else {
stmt.execute((err, result) => {
if(err) {
reject(err);
} else {
stmt.unprepare(err => {
if(err) {
reject(err);
} else {
resolve(result);
}
});
}
});
}
});
});
})
.catch(err => {
console.log(`Prepared statement error: ${err.message}`);
})
.finally(() => {
if (this.connectionPool.connected) {
this.connectionPool.close();
}
});
Now, the catch() and finally() blocks will be sequenced as you expect.

How to escape from .then() without executing the next statement in Express Js Promise?

By using mysql2 with promise, I have the controller.js as below :
exports.company_add = (req, res) => {
company_model.company_add(admin_email, admin_info).then((result) => { ... })
.catch((err) => { ... })
}
And the model.js as below :
exports.company_add = (admin_email, admin_info) => {
return new Promise((resolve, reject) => {
connectionPool.getConnection((connectionError, connection) => {
if (connectionError) reject(connectionError);
return connection.promise().query('SELECT * FROM admin WHERE admin_email = ?', [admin_email])
.then(([rows, field]) => {
if (rows.length) reject('Email exist');
else return connection.promise().query('INSERT INTO companydb.admin SET ?', [admin_info])
})
.then((result) => {
console.log('result')
if (result[0].affectedRows === 1) resolve(result);
else reject('INSERT FAIL');
})
.catch((err) => {
reject(err);
})
.finally(() => {
connection.release();
})
});
});
};
I wonder how I escape from the .then() statement when the line if (rows.length) occurred, since there is no need to continue with the next .then() for this case if the email already exist in the database. Do I need to throw it and add a .catch() just before the next .then() executed?
One cannot really break out of a then chain other than by nesting or throwing an exception. Yes, in this case you probably should throw, but you don't need to .catch it when you avoid the Promise constructor antipattern and just make it a chained promise:
exports.company_add = (admin_email, admin_info) => {
return connectionPool.getConnection().then(connection => {
return connection.promise().query('SELECT * FROM admin WHERE admin_email = ?', [admin_email])
.then(([rows, field]) => {
if (rows.length)
throw new Error('Email exist');
else
return connection.promise().query('INSERT INTO companydb.admin SET ?', [admin_info])
})
.then((result) => {
console.log('result')
if (result[0].affectedRows !== 1)
throw new Error('INSERT FAIL');
return result;
})
.finally(() => {
connection.release();
})
}, err => {
console.error(err);
throw new Error('CONNECTION FAIL');
});
};

How to stub the same method in two test-cases using Sinon?

I am using Node, Mongoose, Sinon, Mocha.
In the DAO layer, I have methods named methodA, methodB. In the service layer, I have servMethodA (calls methodA), servMethodB (calls methodB), servMethodC. Now, servMethodC calls the methodA from DAO and then I have a call to methodB nested in it.
In the test cases for the service layer, I have already stubbed methodA and methodB. How do I stub them again for the test-case for servMethodC?
These are my service methods.
function findLikeByPostIdAndUserId(postId, userId) {
return new Promises((resolve, reject) => {
likeDislikeDao.findLikeByPostIdAndUserId(postId, userId).
then((data) => {
resolve(data);
})
.catch((error) => {
reject(error);
});
});
}
function findDislikeByPostIdAndUserId(postId, userId) {
return new Promises((resolve, reject) => {
likeDislikeDao.findDislikeByPostIdAndUserId(postId, userId).
then((data) => {
resolve(data);
})
.catch((error) => {
reject(error);
});
});
}
function saveLike(like) {
console.log(like);
return new Promises((resolve, reject) => {
console.log(data);
likeDislikeDao.findLikeByPostIdAndUserId(like.postId, like.userId).
then((data) => {
if (!data) {
likeDislikeDao.findDislikeByPostIdAndUserId(like.postId, like.userId).
then((dislikeData) => {
if (!dislikeData) {
likeDislikeDao.saveLike(like).
then((data) => {
resolve(data);
});
}
else {
likeDislikeDao.deleteDislike(dislikeData._id)
.then((data) => {
likeDislikeDao.saveLike(like).
then((data) => {
resolve(data);
});
});
}
});
}
else {
likeDislikeDao.deleteLike(data._id)
.then((data) => {
//likeDislikeDao.saveLike(like).
// then((data) => {
// resolve(data);
// });
resolve(data);
});
}
})
.catch((error) => {
reject(error);
});;
});
}
Here are my individual test cases.
describe('saveLike', function () {
it('should add a like', function () {
var stub = sinontwo.stub(likeDislikeDao, 'saveLike');
stub.withArgs(newLike).callsFake(() => {
return Promise.resolve(newLike);
});
var stubtwo = sinontwo.stub(likeDislikeDao, 'saveDislike');
stubtwo.withArgs(newDislike).callsFake(() => {
return Promise.resolve(newDislike);
});
const stubthree = sinontwo.stub(likeDislikeDao, 'findLikeByPostIdAndUserId');
stubthree.callsFake(() => {
return Promise.resolve(like);
});
const stubfour = sinontwo.stub(likeDislikeDao, 'findDislikeByPostIdAndUserId');
stubfour.callsFake(() => {
return Promise.resolve(dislike);
});
likeDislikeService.saveLike(newLike).then(response => {
console.log('1 -> ');
console.log(response);
assert.length(response, 1);
});
stub.withArgs(like).callsFake(() => {
return Promise.reject('');
});
stubtwo.withArgs(dislike).callsFake(() => {
return Promise.reject('');
});
likeDislikeService.saveLike(like).then(response => {
console.log('2 -> ');
console.log(response);
assert.lengthOf(response, 1);
}).then((err) => {
console.log(err);
assert.isDefined(err);
});
});
});
describe('findLikeByPostIdAndUserId()', function () {
it('should find likes by post id and user id', function () {
likeDislikeService.findLikeByPostIdAndUserId(1,2).then(response => {
assert.length(response, 1);
});
likeDislikeService.findLikeByPostIdAndUserId(1,2).then(response => {
assert.length(response, 1);
}).catch((err) => {
//console.log(err);
assert.isDefined(err);
});
})
});
describe('findDislikeByPostIdAndUserId()', function () {
it('should find dislikes by post id and user id', function () {
likeDislikeService.findDislikeByPostIdAndUserId(1,2).then(response => {
assert.length(response, 1);
});
likeDislikeService.findDislikeByPostIdAndUserId(1,2).then(response => {
assert.length(response, 1);
}).catch((err) => {
console.log(err);
assert.isDefined(err);
});
})
});
Problem is, I am not getting the "reject" part of the find-methods in the coverage. Also, the saveLike method is not being covered properly apart from the 'then' lines.

Simple get request with node.js and express

I have tried everything and can't figure out what i am doing wrong. I have no problem posting data from the client to the server but the other way around i can't get it to work.
The only response i get in my client is ReadableByteStream {}.
This is my code on the client:
export function getAllQuestionnairesAction(){
return (dispatch, getState) => {
dispatch(getAllQuestionnairesRequest());
return fetch(API_ENDPOINT_QUESTIONNAIRE)
.then(res => {
if (res.ok) {
console.log(res.body)
return dispatch(getAllQuestionnairesSuccess(res.body));
} else {
throw new Error("Oops! Something went wrong");
}
})
.catch(ex => {
return dispatch(getAllQuestionnairesFailure());
});
};
}
This is my code on the server:
exports.all = function(req, res) {
var allQuestionnaires = [];
Questionnaire.find({}).exec(function(err, questionnaires) {
if(!err) {
console.log(questionnaires)
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ a: 1 }));
//res.json(questionnaires)
}else {
console.log('Error in first query');
res.status(400).send(err);
}
});
}
I'm doing some guesswork here, since I'm not sure what flavor of fetch you are currently using, but I'll take a stab at it based on the standard implementation of fetch.
The response inside the resolution of fetch typically does not have a directly readable .body. See here for some straight forward examples.
Try this:
export function getAllQuestionnairesAction(){
return (dispatch, getState) => {
dispatch(getAllQuestionnairesRequest());
return fetch(API_ENDPOINT_QUESTIONNAIRE)
.then(res => {
if (res.ok) {
return res.json();
} else {
throw new Error("Oops! Something went wrong");
}
})
.then(json => {
console.log(json); // response body here
return dispatch(getAllQuestionnairesSuccess(json));
})
.catch(ex => {
return dispatch(getAllQuestionnairesFailure());
});
};
}

Resources