Access Output from MySQL in another file - javascript

I want to access the variable "result" from the function which contains the query.
When I want to access it from another file, in which I am trying to work with the output after a POST Request, the variable is declared as "undefined".
This is the file in which i execute the query:
const db = require('../db/connect');
module.exports = {
getID(name){
db.query(`SELECT CWID FROM user WHERE surname = '${name}'`, function(error, result, fields){
if(error) console.log(error);
console.log(result);
});
}
}
And this is the file where I want to work with the data:
router.post('/test', function(req, res){
const data = queries.getID(req.body.name);
console.log(data);
res.render('new test', {title: "test"});
})
Can anybody help me with this?

Here's an example of querying using mysql and async/await. This should do what you would like:
Query file
const db = require('./db/connect');
module.exports = {
getID(name) {
return new Promise((resolve, reject) => {
db.query(`SELECT CWID FROM user WHERE surname = '${name}'`, function(error, result, fields) {
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
}
}
Main File
router.post('/test', async function(req, res){
const data = await queries.getID(req.body.name);
console.log("Query result: ", data);
res.render('new test', {title: "test"});
});
The reason your result is undefined in your initial example is that you're using asynchronous i/o (normal in Node.js). By returning a Promise from getID, we can make async. calls easily and with some nice code syntax.

Related

How to wait for a variable to be populated by an api request before passing it to a webpage as an argument?

I'm new to JavaScript and cannot seem to make this work , the topic of quiz depends on the user input... when the user presses next , I get the topic (this also takes user to the main quiz page), then i have to fetch data from the api with the topic as a parameter... I have to process the result of the fetch operation.. Then I have to pass that info to to the main quiz page... but the variable that is supposed to be populated by the fetch request is still undefined when i pass is to the main quiz page
var Allquestions;
var sheetdb = require('sheetdb-node');
// create a config file
var config = {
address: 'https://sheetdb.io/api/v1/9djmf8ydc7hwy',
};
//sheetdb
// Create new client
var client = sheetdb(config);
function downloadquestions(topic) {
console.log(topic);
client.read({ limit: 2, sheet: topic }).then(function(data) {
console.log(data + " in client.read func")
processQuestions(data);
}, function(err){
console.log(err);
});
}
async function processQuestions(data) {
console.log(data + "data in process");
Allquestions = JSON.parse(data);
console.log(Allquestions[0].Question + " This is defined");
}
app.get("/", (req, res) => {
res.render("pages/index", { title: "Home"});
});
// app.post("/" , urlencodedParser ,(req , res) => {
// console.log(req.body.topic);
// })
app.get("/questions", urlencodedParser , (req , res) => {
downloadquestions(req.body.topic);
console.log(Allquestions + " this is undefined");
res.render("/pages/quizpage" , {Allquestions})
})
There are a few issues with your code, you have a broken promise chain, client.read( is a promise, and that promise is going nowhere. You either return it, or await it. To be able to await your will need to also mark your route (req, res) as async too.
Your code is a little mixed up, you have Allquestions as a global var, this isn't great for multi-user, as the last topic is going to override this each time.
Also try and avoid swallowing exceptions in utility functions, try and keep your exception handling at the top level, eg. in your case inside your req/res handler.
So with all this in mind, your refactored code could look something like ->
const sheetdb = require('sheetdb-node');
// create a config file
const config = {
address: 'https://sheetdb.io/api/v1/9djmf8ydc7hwy',
};
//sheetdb
// Create new client
const client = sheetdb(config);
async function downloadquestions(topic) {
const data = await client.read({ limit: 2, sheet: topic });
return processQuestions(data);
}
function processQuestions(data) {
return JSON.parse(data);
}
app.get("/", (req, res) => {
res.render("pages/index", { title: "Home"});
});
app.get("/questions", urlencodedParser , async (req , res) => {
try {
const allQuestions = await downloadquestions(req.body.topic);
res.render("/pages/quizpage" , {Allquestions});
} catch (e) {
console.error(e);
res.end('There was an error');
}
})

Axios response data is not saved with useState

While trying to fetch data from my express backend and MySQL database, with my react frontend using axios, it fails to set the fetched data using useState
my frontend function looks like this
const searchUser = () => {
Axios.post("http://localhost:3001/searchUser", {
username: username,
}).then((response) => {
if (response.data) {
setResult(response.data);
}
});
};
and my backend function looks like this
const searchUser = (req, res) => {
const keyword = req.body.username;
db.query(
"SELECT id,username FROM users WHERE username like ?",
"%" + keyword + "%",
(err, result) => {
if (err) {
res.json({ message: err });
console.log(err);
} else {
console.log(result);
res.json({ result });
}
}
);
};
I tried many methods while saving the data with the useState hook, I appreciate any help
While using Promises and then instead of async / await make sure to catch the errors if your fetch fails.
Unless you share with us the whole component that contains the searchUser function and how you defined the state i cannot pin point you on the error.
What i suggest you to do is adding a catch to your fetch by doing the following:
const searchUser = () => {
Axios.post("http://localhost:3001/searchUser", {
username: username,
}).then((response) => {
if (response.data) {
setResult(response.data);
}
}).catch((error) => {
console.error(error);
});
};
If any abnormalities has happened in your request the catch will tell you! Don't underestimate it's power.
Another path you can look into is console logging your output in front end searchUser function just before setting it in the state.
I did solve the problem, just by replacing res.json({ result }); to res.json(result); in the last line in my backend function

My Node Script Hangs after functions are finished

I'm calling three functions, after the completion of these functions I want my script to close on it's own but it just hangs.
I've tried making the functions async/promise based, closing the database after each 'mongodb' type function, and using process.exit() within a function as a callback to the last called function.
Connecting to the (local - not Atlas) Database:
MongoClient.connect(local, {useNewUrlParser: true, useUnifiedTopology: true}, function(err, db) {
if (err) {
console.log(err)
}
else {
console.log('Connected to MongoDB...')
//Read in data from jsonfiles and store each file's contents into the database : This is where the functions are being called... within a successful connect to the MongoDB
insertJSON(db, jsonfiles, 'requests', jsonfilesSource)
insertJSON(db, issuedfiles, 'issuedLicenses', isssuedfilesSource)
insertLicenses(db)
}
db.close()
})
Function 1:
function insertJSON(db, dirBuf,collection, sourceFolder) {
var database = db.db('license-server')
var collection = database.collection(collection)
fs.readdir(dirBuf, function(err, files) {
if (err) {
console.log(err.message)
}
else {
files.forEach(function(filename) {
var text = fs.readFileSync(sourceFolder + filename);
var filecontents = JSON.parse(text)
//collection.insertOne(filecontents)
collection.findOne({"DisplayTitle" : filecontents.DisplayTitle, "NodeInformation" : filecontents.NodeInformation, "Date": filecontents.Date})
.then(function(result) {
if(result) {
console.log(`An Item could already be in the database: A file is unique if its display title, nodeinformation, and date are different.
the items display title is ${result.DisplayTitle}`)
return
}
else {
collection.insertOne(filecontents)
console.log(`Added ${filecontents.DisplayTitle} to database`)
}
})
.catch(function(error) {
console.log(error)
})
})
}
})
}
Function 2:
function insertLicenses(db) {
// Set up GridFS to import .lic and .licx files into the database
var database = db.db('license-server')
var collection = database.collection('fs.files')
var bucket = new mongodb.GridFSBucket(database);
var dirBuf = Buffer.from('../license-server/private/licenses')
fs.readdir(dirBuf, function(err, files) {
if (err) {
console.log(err.message)
}
else {
files.forEach(function(filename) {
collection.findOne({"filename": filename}).
then(function(result) {
if(result) {
console.log(`The file ${filename} is already in the database`)
return
}
else {
fs.createReadStream('./private/licenses/' + filename).
pipe(bucket.openUploadStream(filename)).
on('error', function(error) {
assert.ifError(error)
}).
on('finish', function() {
console.log(`Uploaded ${filename}`)
})
}
})
})
}
})
// I tried calling db.close() here since this is the last function to be called. No luck.
}
I'm guessing it has something to do with the mongodb functions having their own way to close themselves but I couldn't seem to find what I was looking for in previous attempts to resolve this issue.
The expected result should be the script closing itself, the actual result is a handing script.
All of these database calls are asynchronous -- the result of this code running is to immediately call db.close and then do the work in insertJSON and insertLicenses. If you were to rewrite this to use async/await (and you'd need to update your other functions as well) the db.close call would close the db, and that would allow the script to exit:
await insertJSON(db, jsonfiles, 'requests', jsonfilesSource)
await insertJSON(db, issuedfiles, 'issuedLicenses', isssuedfilesSource)
await insertLicenses(db)
db.close()
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

Change Woocommerce API functions to async/await using NodeJS in AWS Lambda

I am looking to change a couple of Woocommerce API calls so each function finishes before the next functions proceeds. However, I am unsure how to do this without breaking the specific Node Woocommerce API code.
https://woocommerce.github.io/woocommerce-rest-api-docs/?javascript#create-an-order-note
How can I change those two Woocommerce POST functions to Async/Await so it works with AWS Lambda?
(I have included an existing await function currently used in AWS Lambda as a reference)
const WooCommerceAPI = require('woocommerce-api');
const path = require('path');
const util = require('util');
exports.handler = async (event, context, callback) => {
// AWAIT EXAMPLE in LAMBDA -- Outputs the /tmp/ contents to the console.
const readdirs = util.promisify(fs.readdir);
await readdirs('/tmp/').then((files) => {
console.log('Check tmp contents')', files);
}).catch((err) => {
console.log(err);
});
// Update Woocommerce order
const WooCommerce = new WooCommerceAPI({
url: process.env.WOOAPI_URL, // Your store URL
consumerKey: process.env.WOOAPI_KEY, // Your consumer key
consumerSecret: process.env.WOOAPI_SECRET, // Your consumer secret
wpAPI: true, // Enable the WP REST API integration
version: 'wc/v3' // WooCommerce WP REST API version
});
//Set order as complete
const status = { status: 'completed' };
WooCommerce.post('orders/' + orderId, status, function (err, states, res) {
if (err) throw err;
else console.log('Update WooCommerce order with status');
});
const data = { note: 'Please check www.example.com for full instructions' };
WooCommerce.post('orders/' + orderId + '/notes', data, function (err, data, res) {
if (err) throw err;
else console.log('Manual WooCommerce Order Note');
});
};
There's a method called postAsync for async calls in WooCommerce, you can try something like:
const status = {
status: 'completed'
};
const ordersResult = await WooCommerce.postAsync(`orders/${orderId}`, status).then((data) => {
console.log('Update WooCommerce order with status');
}, (err) => {
console.log(err);
});
const noteData = {
note: 'Please check www.example.com for full instructions'
};
const notesResult = await WooCommerce.postAsync(`orders/${orderId}/notes`, noteData).then((data) => {
console.log('Manual WooCommerce Order Note');
}, (err) => {
console.log(err);
});
Every method can be used in a promified way just adding Async to the method name.
You can take a look to the docs here: https://github.com/woocommerce/wc-api-node#promified-methods
If it doesn't work, you can always use it stacking calls like this:
const status = {
status: 'completed'
};
WooCommerce.post('orders/' + orderId, status, function(err, states, res) {
if (err) throw err;
console.log('Update WooCommerce order with status');
const data = {
note: 'Please check www.example.com for full instructions'
};
WooCommerce.post('orders/' + orderId + '/notes', data, function(err, data, res) {
if (err) throw err;
console.log('Manual WooCommerce Order Note');
});
});

Node.js - howto block around async call. Or non-blocking xmltojs lib

I'm over my head at the moment.
I'm new to node and writing a passportjs module for Freshbooks. There's a Passport function I'm trying to implement that get's a user's profile.
This code uses Passport's OAuth foo to make a request.
this._oauth.post(url, token, tokenSecret, post_body, post_content_type, function (err, body, res) {
if (err) { return done(new InternalOAuthError('failed to fetch user profile', err)); }
try {
var parser = require('xml2json');
var json = parser.toJson(body); //returns a string containing the JSON structure by default
var util = require('util');
console.log(util.inspect(json));
var profile = { provider: 'freshbooks' };
profile.id = json.response.staff.staff_id;
profile.displayName = json.response.staff.first_name + ' ' + json.response.staff.last_name;
profile.name = { familyName: json.response.staff.last_name,
givenName: json.response.staff.first_name };
if (json.response.staff.email) { profile.emails = [{ value: json.response.staff.email }]; }
profile._raw = body;
profile._json = json;
console.log(util.inspect(json));
done(null, profile);
} catch(e) {
done(e);
}
});
I get a response. It's xml. I'm converting it to JSON, but I don't want that actually. I want a plain-old javascript object.
I looked at https://github.com/Leonidas-from-XIV/node-xml2js but the examples don't show how to get the result out.
var parseString = require('xml2js').parseString;
var xml = "<root>Hello xml2js!</root>"
parseString(xml, function (err, result) {
console.dir(result);
});
What do I do to block around this code till the call is complete and get result out? I'm not sure how to merge these two callbacks together.
you can ask xml2json to return object:
var json = parser.toJson(body, {object: true});
if you decide to use async parser then just put your done callback inside json result handler. There is no need to "block" async function:
var parseString = require('xml2js').parseString;
parseString(body, function(err, json) {
// handle error: return done(err)
// do your logic if no error
// ...
// profile._json = json;
// ...
//
// 'return' result
done(null, profile);
});

Categories

Resources