NodeJS request not returned - node.js

Swagger Inspector
This is the source code
API.js
router.post('/curriculum2_section/', (req,res)=> {
curriculum2_section.CREATE(req.body.curr2_section,req.body.curr2_id,req.body.curr2_section_student_amount)
})
curriculum2_section.js
module.exports.CREATE = function CREATE(curr2_section,curr2_id,curr2_section_student_amount) {
var sqlString = `INSERT INTO curriculum2_section(curr2_id,curr2_section,curr2_section_student_amount)VALUES('${curr2_id}',${curr2_section},${curr2_section_student_amount})`
pool.getConnection((err, conn) => {
if(err) throw err
pool.query(sqlString, function (err, rows) {
console.log('Query String:\n '+this.sql);
if(err) throw err
console.log('Data Insert: '+curr2_section+','+curr2_id+','+curr2_section_student_amount)
conn.release();
})
})
}
I've tried using the callback but it doesn't work. I think it because I don't understand how to use it
Please help me

You need to pass the data you want to output to a method on res in order to get output from Express.
Given what you have here, your best bet might be to add a callback as the last parameter of curriculum2_section.CREATE and use that callback to pass data to res.
https://expressjs.com/en/4x/api.html#res
router.post('/curriculum2_section/', (req,res)=> {
curriculum2_section.CREATE(req.body.curr2_section,req.body.curr2_id,req.body.curr2_section_student_amount, (err, data) => {
res.send(data);
});
});
module.exports.CREATE = function CREATE(curr2_section,curr2_id,curr2_section_student_amount, cb) {
var sqlString = `INSERT INTO curriculum2_section(curr2_id,curr2_section,curr2_section_student_amount)VALUES('${curr2_id}',${curr2_section},${curr2_section_student_amount})`
pool.getConnection((err, conn) => {
if(err) throw err
pool.query(sqlString, function (err, rows) {
console.log('Query String:\n '+this.sql);
if(err) throw err
console.log('Data Insert: '+curr2_section+','+curr2_id+','+curr2_section_student_amount)
conn.release();
cb(null, 'Data Insert: '+curr2_section+','+curr2_id+','+curr2_section_student_amount);
})
})
}

Related

Can't work out promises to return values - NodeJS

After searching through countless posts I don't understand why I'm still getting a Promise pending after my awaits. The code below should explain it but I'm trying to pull a MongoDB query of the max value of a column/schema. The console.log within the function is giving me the correct timestamp but I'm trying to pass that out of the inner scope and function to another function.
This is pure NodeJS with only MongoDB imported. Can this be done without any external packages?
export async function getMaxDate() {
var time = MongoClient.connect(url, { useUnifiedTopology: true }, function (err, db) {
if (err)
throw err;
var dbo = db.db(getDB);
dbo.collection(getColl)
.find()
.limit(1)
.sort({ 'timestamp': -1 })
.toArray(function (err, result) {
if (err)
throw err;
time = result[0].time; // THIS IS GIVING THE CORRECT VALUE
console.log(time)
db.close();
});
});
return time
}
export async function getMax() {
var block = await getMaxDate();
return block
}
var t = getMax();
console.log(t); // THIS IS GIVE ME A PROMISE PENDING
getMax() returns a promise, you have to wait for it.
var t = await getMax()
Also getMaxDate uses an async callback that you want to promisify:
export async function getMaxDate() {
return new Promise((resolve,reject) => {
MongoClient.connect(url, { useUnifiedTopology: true }, function (err, db) {
if (err)
return reject(err);
var dbo = db.db(getDB);
dbo.collection(getColl)
.find()
.limit(1)
.sort({ 'timestamp': -1 })
.toArray(function (err, result) {
if(err)
reject(err);
else {
let time = result[0].time; // THIS IS GIVING THE CORRECT VALUE
console.log(time)
db.close();
resolve(time);
}
});
})
});
}
For reference, A is the same thing as B here:
async function A(x) {
if(x)
throw new Error('foo');
else
return 'bar';
}
function B(x) {
return new Promise((resolve,reject)=>{
if(x)
reject(new Error('foo'));
else
resolve('bar');
});
}
Promises came first, then async/await notation was introduced to make common Promise coding practices easier
You can use A and B interchangeably:
async function example1() {
try {
await A(1);
await B(0);
}
catch(err) {
console.log('got error from A');
}
}
async function example2() {
return A(0).then(()=>B(1)).catch((err)=>{
console.log('got error from B');
})
}

How do I get an attached file from CosmosDB using Nodejs SDK?

I'm trying to work with CosmosDB in Nodejs. I have created some Documents in a collection and have added a couple attachments to one of the documents like so:
let dbds = new azure(dbEndpoint, {"masterKey":dbKey})
fs.open("c:/temp/capture.png", "r", (err, fd) => {
if(err) console.log(err);
else{
dbds.createAttachmentAndUploadMedia(documentLink, fs, {contentType:"image/png", partitionKey: partitionKey}, (err, result) =>{
fs.close(fd);
if(err) console.log(err);
else console.log(result);
}
}
}
Now when I read that attachments for that document, I get 2 attachments:
dbds.readAttachments(documentLink, {"partitionKey":partitionKey}).toArray((err, result) => {
if(err) console.log(err);
else {
console.log(result.length); //2
result.forEach(i => console.log(i.id);) //id of each attachment
}
}
Now I need to be able to read the document back and store it locally. There doesn't seem to be any documentation that I can find for doing this in Nodejs. I've tried the following:
let attachment = result[0]; //from result of toArray() above -- first attachment from list
let mediaURI = `${attachment._self}${attachment.media}`
dbds.readMedia(mediaURI, (err, result) => {
if(err) console.log(JSON.parse(err.body).message); //Request url is invalid
else {
//try to write result to file
}
}
How do I create a valid URI to the media in order to download it?
Edit
Based on comments below, I updated my code as follows:
let attachment = result[0]
let mediaURI = attachment.media //here is the change
dbds.readMedia(mediaURI, (err, result) => {
if(err) console.log(JSON.parse(err.body).message);
else {
//try to store the data
}
})
I no longer get an error but instead get a JSON object:
"{"constants":{"O_RDONLY":0,"O_WRONLY":1,"O_RDWR":2,"S_IFMT"‌​:61440,"S_IFREG":327‌​68,"S_IFDIR":16384,"‌​S_IFCHR":8192,"S_IFL‌​NK":40960,"O_CREAT":‌​256,"O_EXCL":1024,"O‌​_TRUNC":512,"O_APPEN‌​D":8,"F_OK":0,"R_OK"‌​:4,"W_OK":2,"X_OK":1‌​},"F_OK":0,"R_OK":4,‌​"W_OK":2,"X_OK":1}"
I got help from some folks at Microsoft on this.
The primary issue was that I wasn't writing the file correctly.
Instead of this
let dbds = new azure(dbEndpoint, {"masterKey":dbKey})
fs.open("c:/temp/capture.png", "r", (err, fd) => {
if(err) console.log(err);
else{
dbds.createAttachmentAndUploadMedia(documentLink, fs, {contentType:"image/png", partitionKey: partitionKey}, (err, result) =>{
fs.close(fd);
if(err) console.log(err);
else console.log(result);
}
}
}
With fs.open fs is not a filestream -- which is what createAttachmentAndUploadMedia is looking for. I had mistakenly assumed that fs was a fs.open created a filestream.
What I wound up doing was the following:
fs.readFile("c:/temp/myimage.jpg",(err, data) => {
if(err) reject(err);
else dbds.svc.createAttachmentAndUploadMedia(docPath,data,{contentType: "image/jpeg"
, partitionKey: "Key"}, (err, result) =>{..}
})
In your example, the mediaURI should just be ${attachment.media} not concatenated with the ${attachment._self}.
Here is an snippet:
return new Promise<any>((resolve, reject) => {
this.documentDbClient.readAttachment(docLink, options, (err, result) => {
if (err)
return reject(err);
resolve(result.media);
});
}).then((medialink) => {
return new Promise<any>((resolve, reject) => {
this.documentDbClient.readMedia(medialink, (err, result) => {
if (err)
return reject(err);
// buffered data
const data = [];
result.on('data', (chunk) => data.push(chunk));
result.on('end', () => {
resolve(data.join(''));
});
// if not buffered
// resolve(result.toString());
});
});
});

Node js foreach done function

Insted of using setTimeout, what should I use after foreach complete?
app.post('/grid', function(req, res){
getResults(req.body.idarray, function(callback){
res.send(callback);
});
});
function getResults(userIds, callback) {
var totalresult = [];
userIds.forEach(function (user) {
sequence
.then(function (next) {
db.query('SELECT given FROM books WHERE user_id = ?', [user.userId], function (err2, result) {
if (err2) throw err2;
next(err, result);
});
})
.then(function (next, err, books) {
db.query('SELECT received FROM encycs WHERE user_id = ?', [user.userId], function (err3, result2) {
if (err3) throw err3;
next(err, result2, books);
});
})
.then(function (next, err, books, encycs ) {
Calculation(books, encycs, function (cb) {
totalresult.push(cb);
});
next();
});
});
setTimeout(function() {
console.log(totalresult); // output ok.
return callback(totalresult); // returning as expected
}, 2000);
}
I dont know what totalresult.length is. So i can't check the length.
So, according to your use case you need to call callback somehow and pass totalresult into it, because that what your external code, code in the route expected.
To do that, you can call callback before calling next of the third .then statement. Like that.
...
.then(function (next, err, books, encycs ) {
Calculation(books, encycs, function (cb) {
totalresult.push(cb);
});
callback(totalresult);
next();
//console.log(totalresult); //output OK.
});
This might work.
Update 1
It is hard to follow with your code. Can't catch up the logic of it. I would propose you Promises approach. I prepared that solution, that might work. It might contain little errors, but it represents the main idea of what you are trying to achieve, and how it can be done.
app.post("/grid", (req, res) => {
getResults(req.body.idarray)
.then(data => {
res.status(200).json(data);
})
.catch(err => {
console.error("Error occured", err);
res.status(500).json(err);
});
});
function getResults(userIds) {
let promises = userIds.map(loadCalculation);
//this will wait until all loadings are done
return Promise.all(promises);
}
function loadCalculation(user) {
//parallel loading of the books and encycs
return Promise.all([loadBooks(user), loadEncycs(user)])
.then(results => {
let books = results[0];
let encycs = results[1];
let totalresult = [];
Calculation(books, encycs, function (cb) {
totalresult.push(cb);
});
return totalresult;
});
}
function loadBooks(user) {
return makeQuery('SELECT given FROM books WHERE user_id = ?', user);
}
function loadEncycs(user) {
return makeQuery('SELECT received FROM encycs WHERE user_id = ?', user);
}
function makeQuery(query, user) {
return Promise((resolve, reject) => {
db.query(query, [user.userId], function (err, result) {
if(err) {
reject(err);
} else {
resolve(result);
}
});
});
}
Please, note that this is not really performant way to load the data from database, at least, I'm sure that you there is a possibility to load all the books and encycs with a single query, because you are using SQL, and it is really flexible language.

Can I return results from npm async parallel inside a function

I would like to return the results from the npm async in nodejs, it returns undefined when I call the function 'findRequestAgent'
findRequestAgent : (agentId) => {
var queries = [];
var datum;
queries.push((callback) => {
MovingAgent.findById(agentId,(err,doc) => {
if (err) {
console.log("There was an error finding the moving agent");
throw err;
}
callback(null, doc)
})
});
queries.push((callback) => {
SelfStander.findOne({ user_id: agentId}, (err, doc) => {
if (err) {
console.log("There was an error finding the self stander");
throw err;
}
callback(null, doc)
})
});
queries.push((callback) =>{
MovingCompany.findOne({custom_id: agentId}, (err, doc) => {
if (err) {
console.log("There was an error finding the self stander");
throw err;
}
callback(null, doc);
})
});
async.parallel(queries, (err, results) => {
if (err) {
console.log("There was an error perfoming async");
throw err;
}
datum = results;
console.log(datum);
});
return datum;
}
What can I do so that when I call the above function 'findRequestAgent' it returns the results
All of the Mongo queries return promises.
var queries = [];
queries.push(
MovingAgent.findById(agentId,(err,doc) => {
if (err) {
console.log("There was an error finding the moving agent");
throw err;
}
return (null, doc);
})
);
...
return Promise.all(queries).then(
(results) => results; //array of results
).catch(
(err) => console.log(err);
)
No need for the async part
As a general rule, asynchronous functions don't return values directly. You need to use another mechanism such as a callback, events, promises.
Without knowing more about your use case, it's hard to know what the right solution is. But you should definitely stop and make sure you understand how asynchronous functions work in JavaScript before continuing.
The easiest solution is to do what you need to do in side the callback passed to .parallel() but again, without knowing more, it can't be said for certain that that will work for your use case.

Node.JS / JavaScript Async Call back issue

I am trying to accomplish the following (should be quite basic and I must be missing something trivial):
Call a function with string that has a select statement
Wait until the DB call completes and the rows (or json equivalent) is returned
Populate http object to return back
Here is code:
util.js
exports.execute = function( query){
if (connection) {
connection.query(query, function(err, rows, fields) {
if (err) throw err;
console.log("from Util - " + JSON.stringify(rows));
return JSON.stringify(rows);
});
}
};
repo.js
var q = "select * from xxx";
var response;
util.execute(q, function (err, r){
if (err){
throw err;
console.log(err);
}
else {
console.log(r);
res.contentType('application/json');
res.write(r);
res.end();
}
});
My problem is while the code within util.js is called and I can see the json in console, it never comes back to the anonymous call back function in the repo.js.
What am I doing wrong here ?
Update
Thanks Ben
I also found the solution in same line ... here is new code:
repo.js:
var send_data = function (req, res, r){
res.contentType('application/json');
res.write(r);
res.end();
}
exports.all = function(req, res){
var q = "select * from XXX";
var response;
util.execute(req, res,q, send_data);
};
util.js:
exports.execute = function(req, res, query, callback){
if (connection) {
connection.query(query, function(err, rows, fields) {
if (err) throw err;
callback(req, res, JSON.stringify(rows)) ;
});
}
};
util.execute only accepts one parameter in your code. It needs to accept a second callback parameter in order to use it the way you do. (Callbacks aren't magic, they're just function calls)
Something like:
exports.execute = function(query,callback){
if (connection) {
connection.query(query, function(err, rows, fields) {
if (err) throw err;
console.log("from Util - " + JSON.stringify(rows));
callback(null,JSON.stringify(rows));
});
}
};
If you'd like it to behave consistently and accept an error parameter, you might want fill that in:
exports.execute = function(query,callback){
if (connection) {
connection.query(query, function(err, rows, fields) {
callback(err,null);
console.log("from Util - " + JSON.stringify(rows));
callback(null,JSON.stringify(rows));
});
}
};

Resources