I can't seem to figure out how to save the results of SomeQuery promise. Essentially I would like to take the value in res and pipe it into parseQuery function and return the final results. How do I make the parsed result accessible to an APIs response.
const neo4j = require('neo4j-driver')
var parser = require('parse-neo4j')
const astria_queries = require('./astriaQueries')
const uri = 'bolt://astria_graph:7687'
const user = 'xxx'
const password = 'xxx'
const someQuery = (query) => {
// run statement in a transaction
const driver = neo4j.driver(uri, neo4j.auth.basic(user, password))
const session = driver.session({ defaultAccessMode: neo4j.session.READ })
const tx = session.beginTransaction()
tx.run(query)
.then((res) => {
// Everything is OK, the transaction will be committed
parseQuery(res)
})
.then(() => {
// Everything is OK, the transaction will be committed
})
.catch((e) => {
// The transaction will be rolled back, now handle the error.
console.log(e)
})
.finally(() => {
session.close()
driver.close()
})
}
const parseQuery = (result) => {
try {
const test = parser.parse(result)
console.log(test)
} catch (err) {
console.log(err)
}
}
module.exports = {
someQuery,
}
It finally clicked with me. Here is the solution I came up with. Hopefully it will help others. If there is a better way please let me know. Thank you #fbiville for you help.
async actions
const neo4j = require('neo4j-driver')
var parser = require('parse-neo4j')
const astria_queries = require('./astriaQueries')
const uri = 'bolt://astria_graph:7687'
const user = 'neo4j'
const password = 'neo'
async function getRecords(query) {
// run statement in a transaction
const driver = neo4j.driver(uri, neo4j.auth.basic(user, password))
const session = driver.session({ defaultAccessMode: neo4j.session.READ })
const tx = session.beginTransaction()
try {
const records = await tx.run(query)
const parseRecords = await parseQuery(records)
return parseRecords
} catch (error) {
console.log(error)
} finally {
session.close()
driver.close()
}
}
async function parseQuery(result) {
try {
const parsedRes = await parser.parse(result)
// console.log(parsedRes)
return parsedRes
} catch (err) {
console.log(err)
}
}
// getRecords(astria_queries.get_data_sources)
module.exports = {
getRecords,
}
api send()
exports.get_data_sources = async (req, res) => {
try {
queryFuns.getRecords(astria_queries.get_data_sources).then((response) => {
res.send(response)
})
} catch (error) {
res.status(500).send(error)
console.log(error)
}
}
Related
I have the following code to create a connection to my MongoDB database, and to store it for future use.
const mongodb = require('mongodb');
const MongoClient = mongodb.MongoClient;
// The database will be defined once a connection to between the cluster and mongodb is created
let _database;
const uri = '';
const databaseName = 'db';
const mongoConnect = () => {
MongoClient.connect(uri)
.then((client) => {
_database = client.db(databaseName);
})
.catch((err) => {
console.log(err);
throw err;
});
};
const getDb = () => {
if (_database) {
return _database;
}
throw 'No database found!';
};
module.exports = {
mongoConnect,
getDb
}
My problem is that _database is undefined until the connection is made. If my website tries to use the database before _database is defined it will throw an error and crash.
I want to make it so instead of crashing, other portions of my code would just wait until _database is not undefined. Sounds like a await/async solution is needed, but I can't wrap my head around how to approach implementing something like that here. Any advice would be great!
First approach: To make mongoConnect an async function and await on it before any of the remaining code is executed.
const mongoConnect = async () => {
try {
const client = await MongoClient.connect(uri);
_database = client.db(databaseName);
} catch(e) {
console.log(err);
throw err;
}
};
In the beginning of your code
await mongoConnect();
//Remaning code here
Second approach: To make getDb function await till database connection is available
const mongodb = require('mongodb');
const MongoClient = mongodb.MongoClient;
const uri = '';
const databaseName = 'db';
const databasePromise = new Promise((resolve, reject) => {
MongoClient.connect(uri)
.then((client) => {
resolve(client.db(databaseName));
})
.catch((err) => {
reject(err);
});
})
const getDb = async () => {
return await databasePromise;
};
module.exports = {
getDb
}
Sample code for you to run and check the second approach:
const databasePromise = new Promise((resolve) => {
console.log("Connecting to db in 5 seconds...")
setTimeout(() => {
console.log("Done")
resolve("done")
}, 5000)
})
const getDb = async () => {
return await databasePromise;
};
console.time("First_getDb_call")
getDb().then(res => {
console.timeEnd("First_getDb_call")
console.log(res)
console.time("Second_getDb_call")
getDb().then(res => {
console.timeEnd("Second_getDb_call")
console.log(res)
})
})
**Pretty Simple approach ** Just add await before MongoClient.connect function and make function async Now It will wait for the connection to have response then move forward.
const mongodb = require('mongodb');
const MongoClient = mongodb.MongoClient;
// The database will be defined once a connection to between the cluster
and mongodb is created
let _database;
const uri = 'mongodb://localhost:27017/mydb';
const databaseName = 'db';
const mongoConnect = async () => {
await MongoClient.connect(uri)
.then((client) => {
_database = client.db(databaseName);
})
.catch((err) => {
console.log(err);
throw err;
});
};
const getDb = () => {
if (_database) {
return _database;
}
throw 'No database found!';
};
module.exports = {
mongoConnect,
getDb
}
i create API With Node.js and SQL Server and its working normally with Get All Data I tested it with postman (200)
.. index.js page
const getEvents = async () => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const eventsList = await pool.request().query(sqlQueries.eventslist);
return eventsList.recordset;
} catch (error) {
console.log(error.message);
}
}
and the eventController.js page
const getAllEvents = async (req, res, next) => {
try {
const eventlist = await eventData.getEvents();
res.send(eventlist);
} catch (error) {
res.status(400).send(error.message);
}
}
and eventlist.sql
SELECT [employee_id]
,[first_name]
,[last_name]
,[email]
,[phone_number]
,[hire_date]
,[job_id]
,[salary]
,[manager_id]
,[department_id]
FROM [sales].[dbo].[employees]
******************* But with read single post (Error)
index.js page
const getById = async(eventId) => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const event = await pool.request()
.input('employee_id', sql.Int, eventId)
.query(sqlQueries.eventbyId);
return event.recordset;
} catch (error) {
return error.message;
}
}
And and the eventController.js page
const getEvent = async (req, res, next) => {
try {
const eventId = req.params.id;
const event = await eventData.getById(eventId);
res.send(event);
} catch (error) {
res.status(400).send(error.message);
}
}
and eventlbyId.sql
SELECT [employee_id]
,[first_name]
,[last_name]
,[email]
,[phone_number]
,[hire_date]
,[job_id]
,[salary]
,[manager_id]
,[department_id]
FROM [sales].[dbo].[employees] WHERE [employee_id]=#employee_id
the Res From postman
<pre>Cannot GET /api/events/100</pre>
I couldn't get my for loop to run synchronously.The order of registration that it returns for each domain changes. I guess whichever answers the fastest brings those records first. Where am I doing wrong?
const rrtypes= ["A","MX","CNAME","NS","TXT"];
var resData = [];
export const getAllRecords = async (req,res) => {
const {domain} = req.params;
for await(const rrtype of rrtypes){
dns.resolve (domain, rrtype, (err, records) => {
resData.push(rrtype+" "+records);
});
}
res.send(resData);
resData = [];
}
Notice that you can use the dns.promises.resolve function: https://nodejs.org/api/dns.html#dns_dnspromises_resolve_hostname_rrtype
so you would change your code to:
const rrtypes = ["A", "MX", "CNAME", "NS", "TXT"];
export const getAllRecords = async (req, res) => {
const { domain } = req.params;
// Notice that resData should be local to this function
let resData = [];
for (const rrtype of rrtypes) {
try {
const records = await dns.promises.resolve(domain, rrtype);
resData.push(rrtype + " " + records);
// IMO this would be better: resData.push({ type: rrtype, value: records });
} catch (err) {
// Log the error here
}
}
res.send(resData);
};
The problem lies in your use of await. await should be used when calling async functions. At the moment you are using it when instantiating variables from an array.
Thanks to a comment by slebetman I was able to see this dns.resolve does not return a promise but uses callbacks to manage the async calls. As he also suggested we can fix this by creating a promise to manage these callbacks.
const rrtypes= ["A","MX","CNAME","NS","TXT"];
var resData = [];
const dnsResolvePromise = (domain, rrtype) => {
return new Promise((resolve, reject) => {
dns.resolve(domain, rrtype, (err, records) => {
if(err) return reject(err);
resolve(rrtype+" "+records);
});
})
}
export const getAllRecords = async (req,res) => {
const {domain} = req.params;
for(const rrtype of rrtypes){
try{
const records = await dnsResolvePromise(domain, rrtype);
resData.push(records);
} catch (e){
// Handle error
}
}
res.send(resData);
resData = [];
}
So what I am trying to do here is get user by id and then show it but seems like my knowledge is lacking and would be happy if someone could point out the mistakes! Code below:
//routes.js
const routes = require('express').Router();
const dbService = require('./database');
routes.get('/products', async (req,res) => {
try {
const resultat = await dbService.getProducts();
res.json(resultat)
}
catch(error)
{
console.log(error);
}
});
routes.get('/user/:id', async (req,res) => {
try
{
const id = req.params.id
const user = await dbService.getUserId(id);
res.send(user);
console.log(user);
}
catch(error)
{
res.send('error..');
}
});
//database.js
const getUserId = async (data) => {
try
{
const dbCon = await dbPromise;
const user = dbCon.get('SELECT * FROM users WHERE id = (?)', [data.id]);
return user;
}
catch(error)
{
throw error;
}
};
I have this request handler on my node server. It has three MongoDB queries, and I want all the results to be returned, before the response is sent.
api.get('/getStats/:productID', (req,res)=>{
let data = {};
let dailySales = [];
let avgProduct = "";
let customers = [];
Sales.find({productID: productID}).then(
sales => {
dailySales = sales;
}
);
Products.find({}).then(
products => {
// Calculate Avg product here
avgProduct = result;
}
);
Customers.find({}).then(
customers => {
customers = customers;
}
);
data = {
dailySales,
avgProduct,
customers
};
res.json(data);
});
But running this returns
data: {
dailySales: [],
avgProduct: "",
customers: []
}
i.e. The Mongo response is returning before the data is run. Please how to I fix. Thank You
wait for all the promises to resolve before sending the actual response
const sales = Sales.find({productID: productID});
const allProducts = Products.find({});
const allCustomers = Customers.find({});
Promise.all([sales, allProducts, allCustomers])
.then(data => res.json(data));
you can try using the Promise.all where you can pass the MongoDB queries as parameter to it ,the promise will be resolved when all the queries return the result in the array
Try using the in-built util.promisify function along with
async-await to get data correctly!
const promisify = require('utils').promisify;
const salesFindOnePromise = promisify(Sales.find);
const productsFindAllPromise = promisify(Products.find);
const customersFindAllPromise = promisify(Customers.find);
findDailySalesByIdAsync = async (productID) => {
try {
return await salesFindOnePromise({ productID: productID });
} catch(err) {
throw new Error('Could not fetch the appropriate sales with productID');
}
}
findProductsAsync = async () => {
try {
return await productsFindAllPromise({});
} catch (err) {
throw new Error('Could not fetch sales!');
}
}
findCustomersAsync = async () => {
try {
return await customersFindAllPromise({});
} catch (err) {
throw new Error('Could not fetch customers!');
}
}
api.get('/getStats/:productID', async (req,res)=>{
try {
const dailySales = await findDailySalesByIdAsync(productID);
const avgProduct = await findProductsAsync();
const customers = await findCustomersAsync();
const data = {
dailySales,
avgProduct,
customers
};
return res.status(200).send(data);
} catch(err) {
console.err(`Failed because: {err}`);
throw new Error('Could not fetch data because of some error!');
}
});