Unable to use async await with sequelize.authenticate() method - javascript

The SQL password expires every 24 hour once (The interval might change anytime without prior notice), hence I want to validate the authentication using Sequelize beforeConnect hook before I run a SQL query.
Without async await the SQL query will fail and then authenticate and the preceding queries will pass. I want to run the code async way so no SQL queries fail. Kindly help me fix this problem.
const sequelize = new Sequelize(database, username, password, params);
sequelize.beforeConnect(async (currConfig) => {
try {
await sequelize.authenticate();
console.log('Connection has been established successfully.');
} catch (error) {
console.error('Unable to connect to the database:', error);
}
});

You can promisify the beforeConnect
let currConfig = await prepare(sequelize);
try {
await sequelize.authenticate();
console.log("Connection has been established successfully.");
} catch (error) {
console.error("Unable to connect to the database:", error);
}
function prepare(sequelize) {
return new Promise(res => {
sequelize.beforeConnect(config => res(config));
});
}
Just make sure your function has async infront of it

Related

How to connect to a MongoDB asynchronously?

I have a MongoDB database. I'm using Javascript and Node.js (using Mangoose) to access this database. I need to return an array with the name of all the collections in the database. So I use a code that follows.
let connection = mongoose.createConnection(process.env.MONGODB_URI + "/" + dbname);
// Wait 10 seconds for Mongoose to establish the connection.
await new Promise(r => setTimeout(r, 10000));
return connection.db.collections()
.then(stations=>stations.map(stations=>stations.collectionName))
.catch(reason => {
console.error("Error : "+reason);
return null;
});
The code above is working correctly. Now, I'm trying to do the same process asynchronously. For this, I am using the following code.
async function station_list_all(dbname){
return new Promise((resolve,reject) => {
try {
let connection = mongoose.createConnection(process.env.MONGODB_URI + "/" + dbname);
resolve(connection);
}catch(err){
reject(new Error("DB not found!"));
}
})
.then(connection => connection.db)
.then(db => db.collections())
.then(stations=>stations.map(station=>station.collectionName))
.catch(err => {
console.error("Error : "+err);
return null;
});
}
Unfortunately, instead of the collection names, I get the message: Error : TypeError: Cannot read property 'collections' of undefined.
I think db is returning undefined, but... Shouldn't the code wait until db has a valid value?
Try with async await:
try {
await mongoose.connect('mongo url with db name');
// other process
} catch (error) {
handleError(error);
}
Or you can connect using callback:
try {
mongoose.connect('mongo url with db name').then(()=>{
// other process
});
} catch (error) {
handleError(error);
}
In Same way you can try with promise also. There is no need use settimeout.
For More Ref Please visit: Mongoose Connections

Await Receiving Warning while in try-catch Block

The first await below generates the warning 'await' has no effect on the type of this expression if I do not include the .catch line immediately found after (and currently commented out). However, all the code is included in a try-catch block. Why am I receiving this warning? Isn't the MongoClient.connectan asynchronous call?
const db = null
async function dbConnect() {
try {
const client = await MongoClient.connect(url, {useUnifiedTopology: true})
// .catch(err => { console.log(err) })
if (!client) throw new Error("Database Not Available")
db = await client.db(dbName)
} catch (err) {
console.log(err)
}
}
dbConnect()
.connect() returns a promise not a client. Try this code:
const db = null
async function dbConnect() {
try {
const client = new MongoClient(url)
await client.connect({useUnifiedTopology: true})
db = await client.db(dbName)
} catch (err) {
console.log(err)
}
}
dbConnect()

Method does not catch firestore timeout error

I have following code where I cannot catch Firestore timeout error when internet is slow. It just returns empty array.
static getEspeciallyProducts() {
return new Promise(async (resolve, reject) => {
try {
const db = Firebase.firestore(),
products = [],
activeRef = await db.collection("products")
.orderBy("id")
.withConverter(ProductConverter)
.get();
for (let doc of activeRef.docs) {
const data = doc.data();
if (_.isObject(data))
products.push(data);
}
resolve(products);
} catch (error) {
reject(error);
}
});
}
However, my another method catches an error:
static getProductById(id) {
return new Promise(async (resolve, reject) => {
try {
const docRef = Firebase.firestore().collection("products").doc(id),
doc = await docRef.withConverter(ProductConverter).get();
if (doc.exists)
resolve(doc.data());
else
resolve(null);
} catch (error) {
reject(error);
}
});
}
Firestore doesn't throw errors in the event that the internet connection is slow or down. It either:
Silently retries until the connection is available, or
Gives up and falls back to the local persistence layer.
If it does #2, you will see a message in the console log about that. But the code making a query will not just fail. Failure are only given for errors that cannot be recovered, such as security rule violations and exceeded limits.
If you want code to fail in the event of a network problem, consider using the REST API instead.

Transaction for prepared statements using Node mssql

I want to create an Express REST API and will use MSSQL for the database part. I use the mssql module and use the PreparedStatement class.
Sometimes my queries have to be transactional, so I have to work with the Transaction class too.
I found some information about prepared statements here and about transactions here but don't know how to execute transactional queries using prepared statements.
Would someone mind explaining how to use the mssql module with prepared statements within transactions? My query function should provide a functionality giving access to write something like this in my query file
begin transaction
run prepared statement one
run prepared statement two
end transaction
So to reproduce the problem:
First I created a database with a table called "integer" and a numeric column "value".
Then I created an empty Node/Typescript project with this code:
import sql, { ConnectionPool, PreparedStatement } from 'mssql';
class App {
private connectionPool: ConnectionPool;
constructor() {
this.connectionPool = new sql.ConnectionPool(databaseConfig);
}
public run = async (): Promise<void> => {
try {
await this.connectionPool.connect();
const preparedStatement: PreparedStatement = new sql.PreparedStatement(this.connectionPool);
preparedStatement.input('number', sql.Numeric(18, 0));
await preparedStatement.prepare('INSERT INTO integer (value) VALUES (#number)');
await preparedStatement.execute({ number: 1 });
await preparedStatement.unprepare();
console.log('done...');
} catch (error) {
throw error;
}
}
}
(async () => {
const app: App = new App();
await app.run();
})().catch(error => {
throw error;
});
So far so good. Now I want to run two INSERTs within a transaction but the second one passes in a string so I would expect an error and the first one gets rolled back. My updated run function:
public run = async (): Promise<void> => {
try {
await this.connectionPool.connect();
const transaction: Transaction = new sql.Transaction(this.connectionPool);
const workingStatement: PreparedStatement = new sql.PreparedStatement(transaction);
workingStatement.input('number', sql.Numeric(18, 0));
const invalidStatement: PreparedStatement = new sql.PreparedStatement(transaction);
invalidStatement.input('number', sql.Numeric(18, 0));
try {
await transaction.begin();
await workingStatement.prepare('INSERT INTO integer (value) VALUES (#number)');
await workingStatement.execute({ number: 1 });
await workingStatement.unprepare();
await invalidStatement.prepare('INSERT INTO integer (value) VALUES (#number)');
await invalidStatement.execute({ number: false });
await invalidStatement.unprepare();
await transaction.commit();
} catch (error) {
await transaction.rollback();
console.log('execution failed...');
}
console.log('done...');
} catch (error) {
throw error;
}
}
Now I get this error
(node:18416) UnhandledPromiseRejectionWarning: TransactionError: Can't
rollback transaction. There is a request in progress.
And I'm not sure if my syntax is wrong.
I believe the error you're hitting happens because you didn't call unprepare as suggested in the docs:
keep in mind you can't execute other requests in the transaction until you call unprepare
Calling unprepare on the statement before rolling back the transaction works for me:
try {
// ...
await invalidStatement.prepare('INSERT INTO integer (value) VALUES (#number)');
try {
await invalidStatement.execute({ number: false });
} finally {
await invalidStatement.unprepare();
}
} catch (error) {
// rollback here...
}

Properly terminate NodeJS Async Await

I wrote the following code to connect to MongoDB wrapped in a Promise, but as soon as it is connected, my NodeJS code is still running / not exit properly. May I know what is the proper way to return or terminate it?
function connectDB() {
return new Promise (resolve => {
MongoClient.connect(mongoUrl, function( err, db ) {
_db = db;
resolve(db);
});
})
}
(async function crawl() {
const db = await connectDB();
console.log('You are connected');
})()
This isn't really related to async/await, it also happens without. As #Torazaburo stated in the comments, the db driver maintains an open connection to the database, and this open socket (along with its eventhandlers) prevents node from quitting. Closing the connection helps:
function connectDB() {
return new Promise (resolve => {
MongoClient.connect(mongoUrl, function(err, db) {
if (err) reject(err);
else resolve(db);
});
});
}
(async function crawl() {
const db = await connectDB();
console.log('You are connected');
db.close();
console.log('You are no longer connected. Bye!');
})()
A promise have 2 paramaters: resolve and reject.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
You need to change your promise declaration:
return new Promise ((resolve, reject) => {
// ...
}
After that, add return statement to your promise:
return resolve(db)
Also, i suggest you to add an error log to your promise:
if (err) return reject(err)
And catch this error.
Good luck!

Categories

Resources