Please help me solve JavaScript Asyncronus issue - javascript

I have code in connect.js like this
const sqlite3 = require('sqlite3').verbose();
class Connection {
static connect() {
let db = new sqlite3.Database('../SQlite-tester-001/db/sqlite_tester001.db', sqlite3.OPEN_READWRITE, (err) => {
if (err) {
console.error(err.message);
}
else {
console.log('Connected to the tester database.');
}
});
return db
}
}
module.exports = Connection;
And I try to call it from insert.js like this
const Connection = require('./connect');
(async () => {
let db = await Connection.connect();
await console.log('This line is below Connection.connect()');
})();
console.log('This line is below Async function');
However, the result is not what I wanted like below
wittinunt#Wittinunt-VCIS-PC:~/GitHub/SQlite-tester-001$ node insert.js
This line is below Async function
This line is below Connection.connect()
Connected to the tester database.
What I expected it is should be like
Connected to the tester database.
This line is below Connection.connect()
This line is below Async function
I'm very new to JavaScript and now I very confuse about 'async-await'.
Please help.

There are callback/Promise/asny,await ways to handle asynchronous
And in the above code, callback and async/await are used in duplicate among the asynchronous handling methods.
The callback function works.
So delete the callback function and run.
[However, the function must support Promise]
const sqlite3 = require('sqlite3').verbose();
class Connection {
static async connect() {
try {
let db = await new sqlite3.Database('../SQlite-tester-001/db/sqlite_tester001.db', sqlite3.OPEN_READWRITE);
console.log('Connected to the tester database.');
} catch (err) {
console.error(err.message);
}
}
}
module.exports = Connection;
if error occrued, then "catch block" catch error.

Related

noting is working in catch block in node js

i have a simple express server in which i have function, in this function i try to access data from mongoDB , here is the code
const test =async()=>{
try{
const data = await User.findOne({_id: "1234"})
}catch(err){
const data = await User.findOne({_id: "4567"})
}
in this function, try block is working fine but whenever error occurs code inside catch block is not working, i have try return and console.log() in catch block which is also not working, here is code
catch(err){
console.log("hello")
}
or
catch(err){
return "hello"
}
nothing is not working in catch block, i cant understand this problem please help me
Edit
the above code is simple example of my problem the actual code is following
router.post("/", async (req, res) => {
const data = req.body;
data.time = new Date();
data._id = uniqid();
data.orderStatus = "Pending";
const tradeData = await TradePara.create(data);
try {
algoTrade(data);
} catch (err) {
console.log(err);
}
});
i am facing issue with the algoTrade function, inside this function i am calling some apis with axios
I see the issue with your code in comments. The issue is that catch block is not implemented to catch error thrown by try block hence the code terminates use it like this
router.post("/", async (req, res) => {
const data = req.body;
data.time = new Date();
data._id = uniqid();
data.orderStatus = "Pending";
const tradeData = await TradePara.create(data);
try {
algoTrade(data);
} catch(e) {
console.log("not working", e);
}
});
instead of using catch{}, implement catch block.

NodeJS ASync call of MongoClient GetData routine

The code below is a mix of https://www.w3schools.com/nodejs/nodejs_mongodb_find.asp
and
https://stackoverflow.com/questions/49982058/how-to-call-an-async-function#:~:text=Putting%20the%20async%20keyword%20before,a%20promise%20to%20be%20resolved.
When you look at the console.log below the code, things seem to be running out of order. I thought by making the function async and using the .then I would avoid those issues.
I want the MongoDB data retrieval function separate from the app.get function.
No data is being returned to the get request. I guess the app.get code is falling through and ending before the function returns the value. What do I need to correct?
async function getLanguageTranslationData(fromLanguage, toLanguage) {
console.log("Started getLanguageTranslationData")
const databaseUrl = "mongodb://localhost:27017"
const databaseName = 'MyCompanyPOC'
mongoClient.connect(databaseUrl, function(err, conn) {
if (err) throw err;
const collectionName = "Phrases";
var dbo = conn.db(databaseName)
var query =
{ $and:
[ {masterLanguage: fromLanguage},
{localizedLanguage: toLanguage}
]
}
console.log("query=" + JSON.stringify(query));
console.log("about to retrieve data");
dbo.collection(collectionName).find(query).toArray(
function(err, result) {
if (err) throw err;
console.log("Back from mongoDB.find()")
console.log(JSON.stringify(result))
return result
conn.close()
})
})
}
app.get("/api/gettranslations/:fromLanguage/:toLanguage",
async function(req, res) {
console.log("Backend: /api/gettranslations method started: " +
" fromLanguage=" + req.params.fromLanguage +
" toLanguage=" + req.params.toLanguage)
getLanguageTranslationData(
req.params.fromLanguage,
req.params.toLanguage)
.then((arrayResult) => {
console.log("got arrayResult back from getLanguageTranslationData")
res.status(200).json(arrayResult)
console.log("Backend: End of /api/gettranslations process")
})
})
Node.JS Console output:
listening on port 3001
Backend: /api/gettranslations method started: fromLanguage=en-US toLanguage=es-MX
Started getLanguageTranslationData
(node:44572) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
got arrayResult back from getLanguageTranslationData
Backend: End of /api/gettranslations process
query={"$and":[{"masterLanguage":"en-US"},{"localizedLanguage":"es-MX"}]}
about to retrieve data
Back from mongoDB.find()
[{"_id":"5f403f7e5036d7bdb0adcd09","masterLanguage":"en-US","masterPhrase":"Customers","localizedLanguage":"es-MX","localizedPhrase":"Clientes"},{ etc...
The thing is getLanguageTranslationData should return a promise so that you can use it as a promise in your handler, but in your case, call to getLanguageTranslationData will return undefined as all the code inside this function will execute asynchronously due to nodejs non-blocking nature.
So what you can do is return promise from your getLanguageTranslationData function like this.
function getLanguageTranslationData(fromLanguage, toLanguage) {
const databaseUrl = "mongodb://localhost:27017"
const databaseName = 'MyCompanyPOC'
return new Promise((resolve, reject)=>{
mongoClient.connect(databaseUrl, function(err, conn) {
if (err) reject(err);
else{
const collectionName = "Phrases";
var dbo = conn.db(databaseName)
var query =
{ $and:
[ {masterLanguage: fromLanguage},
{localizedLanguage: toLanguage}
]
}
dbo.collection(collectionName).find(query).toArray(
function(err, result) {
if (err) reject(err);
else
resolve(result);
})
}
})
})
}
and then use await in your handler to use that promise returned
app.get("/api/gettranslations/:fromLanguage/:toLanguage",
async function(req, res) {
try{
let arrayResult = await getLanguageTranslationData(req.params.fromLanguage, req.params.toLanguage);
res.status(200).json(arrayResult)
}catch(err){
// return error
}
})
The above code will give you the gist of what you need to do, actual code may vary according to your needs.
You can refer async-await from here
I got it working in this way, based on this example: Node.js, Mongo find and return data
#Namar's answer is probably correct too, but I was testing this the same time he posted. As the StackOverflow question/answer above notes, the up-to-date versions of MongoClient have support for promises. That post also shows how to put in a separate module, which is something I will probably do later this week.
function getLanguageTranslationData(fromLanguage, toLanguage) {
console.log("Started getLanguageTranslationData")
const databaseUrl = "mongodb://localhost:27017"
const databaseName = 'ShedCompanyPOC'
return mongoClient.connect(databaseUrl)
.then(function(conn) {
var collectionName = "UploadedDataeFromExcel";
var dbo = conn.db(databaseName)
var query =
{ $and:
[ {masterLanguage: fromLanguage},
{localizedLanguage: toLanguage}
]
}
console.log("query=" + JSON.stringify(query));
console.log("about to retrieve data");
var collection = dbo.collection(collectionName)
return collection.find(query).toArray();
}).then(function(result) {
console.log("Back from mongoDB.find()")
console.log(JSON.stringify(result))
//conn.close()
return result
});
}
app.get("/api/gettranslations/:fromLanguage/:toLanguage",
async function(req, res) {
console.log("Backend: /api/gettranslations method started: " +
" fromLanguage=" + req.params.fromLanguage +
" toLanguage=" + req.params.toLanguage)
getLanguageTranslationData(
req.params.fromLanguage,
req.params.toLanguage)
.then(function(arrayResult) {
console.log("got arrayResult back from getLanguageTranslationData")
res.status(200).json(arrayResult)
console.log("Backend: End of /api/gettranslations process")
}, function(err) {
console.log("The promise was rejected", err, err.stack)
})
})

How to make nodejs wait for mongodb connection before continuing (calling async in blocking way)

I want my nodejs app to not continue unless it connects to mongodb.
I tried:
//Mongo
async function mongoConnect(mongoDB) {
var mongoConnectionSuccessful = false;
LOG("Connecting to mongodb at " + mongoDB + "...");
while (!mongoConnectionSuccessful) {
try {
await mongoose.connect(mongoDB, { useNewUrlParser: true, useUnifiedTopology: true });
LOG("connected!");
mongoConnectionSuccessful = true;
mongoose.connection.on('error', ()=>LOG('MongoDB connection error:'));
return;
} catch (error) {
LOG(error);
}
await utils.sleep(500);
}
}
mongoConnect(config.mongoUrl);
but in order to use await in mongoose.connect, I must make mongConnect async, but I then cannot call it in a blocking way from the code because in order to call like this, I must call with await, but await is only permitted inside async functions.
I must call with await, but await is only permitted inside async functions
That's correct. So do just that:
async function main () {
await mongoConnect(config.mongoUrl);
// rest of your code...
}
main();
For example if this is an Express server do something like:
const express = require('express');
const app = express();
async function main () {
await mongoConnect(config.montoUrl);
const routes = require('./my-routes');
app.use(routes);
app.listen(config.port);
}
main();
You want to attempt reconnect if mongoose fails to connect. Here is an example logic without helper lib.Props to the guy who posted this solution in a github issue for mongoose. Here
function createConnection (dbURL, options) {
var db = mongoose.createConnection(dbURL, options);
db.on('error', function (err) {
// If first connect fails because mongod is down, try again later.
// This is only needed for first connect, not for runtime reconnects.
// See: https://github.com/Automattic/mongoose/issues/5169
if (err.message && err.message.match(/failed to connect to server .* on first connect/)) {
console.log(new Date(), String(err));
// Wait for a bit, then try to connect again
setTimeout(function () {
console.log("Retrying first connect...");
db.openUri(dbURL).catch(() => {});
// Why the empty catch?
// Well, errors thrown by db.open() will also be passed to .on('error'),
// so we can handle them there, no need to log anything in the catch here.
// But we still need this empty catch to avoid unhandled rejections.
}, 20 * 1000);
} else {
// Some other error occurred. Log it.
console.error(new Date(), String(err));
}
});
db.once('open', function () {
console.log("Connection to db established.");
});
return db;
}
// Use it like
var db = createConnection('mongodb://...', options);
and with a lib promise-retry
const promiseRetry = require('promise-retry')
const options = {
useNewUrlParser: true,
reconnectTries: 60,
reconnectInterval: 1000,
poolSize: 10,
bufferMaxEntries: 0 // If not connected, return errors immediately rather than waiting for reconnect
}
const promiseRetryOptions = {
retries: options.reconnectTries,
factor: 2,
minTimeout: options.reconnectInterval,
maxTimeout: 5000
}
const connect = () => {
return promiseRetry((retry, number) => {
logger.info(`MongoClient connecting to ${url} - retry number: ${number}`)
return MongoClient.connect(url, options).catch(retry)
}, promiseRetryOptions)
}
module.exports = { connect }
I found the solution in this article
I beleive what you need is to promise your call of mongoConnect(config.mongoUrl),
than await promises until it is called back.
async function getConcurrently() {
let promises = [];
promises.push(mongoConnect(config.mongoUrl))
// promises.push(getUsers());
// promises.push(getCategories());
// promises.push(getProducts());
let mongo = await Promise.all(promises);
//let [users, categories, products] = await Promise.all(promises);
}
Please Note this warning in the article:
As the first example, first we create an array of Promises (each one of the get functions are a Promise). Then, we execute all of them concurrently and simultaneously, awaiting for all of them to finish (await Promise.all). Finally, we assign the results to the respective variables users, categories and products. Despite the fact that it works, it’s important to say that using Promises.all() for everything is a bad idea.
I assume that for some reason you have incoming events meanwhile you are attempting to connect to mongo. My approach would be preventing any incoming events (such as starting the server and setting listeners) before connection to mongo. If it's not possible, one way to do it is to use a self-invoking function.
//Mongo
async function mongoConnect(mongoDB) {
var mongoConnectionSuccessful = false;
LOG("Connecting to mongodb at " + mongoDB + "...");
while (!mongoConnectionSuccessful) {
try {
await mongoose.connect(mongoDB, { useNewUrlParser: true, useUnifiedTopology: true });
LOG("connected!");
mongoConnectionSuccessful = true;
mongoose.connection.on('error', ()=>LOG('MongoDB connection error:'));
return;
} catch (error) {
LOG(error);
}
await utils.sleep(500);
}
}
(async function() {
// do stuff
await mongoConnect(config.mongoUrl);
// do other stuff
})();

Synchronous and asynchronous vs callback in mongoose

hi guys i am new in node and have this simple question , what is difference between this two sniped
Note: i know async / await functionality and also in front-end application it is best practice for handle async action but in node in working with mongoose i want know which approach better for handle
first solution
// for example we pass this function as controller to route handler
exports.myController = async (req, res, next) => {
try {
const data = await Model.find();
const some = await new Model(data).save();
} catch(e) {
next(e);
}
}
second solution
exports.myController = (req, res, next) => {
const data = Model.find((err, data_) => {
const some = new Model(data_);
some.save((err, result) => {
....
})
});
}
i want to know when i have an error from mongoose , in second way can throw error like this
// in callback function
if (err) {
throw Error();
}
but how can i handle this in async/await solution
you simply throw it or log it in your catch block:
try {
const data = await Model.find();
const some = await new Model(data).save();
} catch(e) {
throw e;
next(e);
}
the async/await is working like promises but without no nesting callbacks and it throws an error synchronous to what errors first and stop from executing the other lines.
Based in your edited Note:
you should always go for the async solution way in nodejs or even for anything related to javascript it's the best composable and reusable solution.

Using mssql in nodejs (function to insert row)

So, I'm new to Nodejs, and now I am trying to make an insert, based on an action I receive from a client.
I have a functions module, which is called by the routes to make certain tasks. Each action needs to be recorded in a mssql table, so I chose to use mssql from npm.
https://www.npmjs.com/package/mssql
Each function in the functions module calls the saveActionToDB function which received an action and a username to make the insert into the table like this:
function saveActionToDB(action, user){
if (config.Logging.DB.type == 'mssql'){
const dbOptions = {
user: config.Logging.DB.user,
password: config.Logging.DB.password,
server: config.Logging.DB.server,
database: config.Logging.DB.database,
options: {
encrypt: config.Logging.DB.encrypt
}
};
const database = require('mssql');
async () => {
try{
const pool = await database.connect(dbOptions);
const result = await database.query(`insert into actions (action, user) values ("${action}", "${user}")`);
console.log(pool);
}
catch (err){
console.log(err);
combinedLogger.error(err);
}
}
}
else if(config.Logging.DB.type == 'oracle'){
//oracle
}
}
The app needs to have the ability to use either mssql or oracle. That;s why it checks the config.Logging.DB.type val to use each of the two.
Right now, the functions call the saveActionToDB, but it doesn't do anything. No errors either. I am guessing it's an issue with the async thing.
Note that I don't need to wait for the saveActionToDB to end in order to respond to the client.
Can anyone help?
You are not calling your async function. This just declares a function but does not execute. async () => {
Looks at this example
console.log('a');
x = async () => {
console.log('b');
}
console.log('c');
x();
the output is a c b. However if I do
console.log('a');
async () => {
console.log('b');
}
console.log('c');
Output is just a c.

Categories