I have the following code to connect to Mongoose DB using Node.js. But I get some kind of warning or refactor notification from VS code to remove await from the the part when I try to connect.
Its say that: await has no effect in this kind of expression
From the documentation of Mongoose inside index.d.ts file;
export function connect(uri: string, options?: ConnectOptions): Promise<Mongoose>; returns promise
So I try to do like this:
// Provide connection to a new in-memory database server.
const connect = async () => {
// NOTE: before establishing a new connection close previous
await mongoose.disconnect()
mongoServer = await MongoMemoryServer.create()
try {
const mongoUri = await mongoServer.getUri()
await mongoose.connect(mongoUri, opts) // No need to use await??
} catch (error) {
console.log(error)
}
Related
I followed this tutorial to set up MongoDB in my Next.js application: https://www.mongodb.com/developer/languages/javascript/nextjs-with-mongodb.
In a file called mongodb-config.js, I have
import { MongoClient } from 'mongodb'
const uri = process.env.MONGODB_URI
const options = {
useUnifiedTopology: true,
useNewUrlParser: true,
}
let client;
let dbPromise;
if (!process.env.MONGODB_URI) {
throw new Error('Please add your Mongo URI to .env.local')
}
// In production mode, it's best to not use a global variable.
client = new MongoClient(uri, options)
dbPromise = client.connect()
// Export a module-scoped MongoClient promise. By doing this in a
// separate module, the client can be shared across functions.
export default dbPromise
The above is how I configure my database.
When I need to use the database for my API, I do:
import dbPromise from "database/mongodb-config";
let db;
dbPromise.then((value) => {
const client = value;
db = client.db("database_name");
})
.catch((error)=>{
console.error(error);
});
db will be the variable that links to my database.
Now, I want to simplify this process and put everything in one file.
In the portion where I set up dbPromise in mongodb-config.js, I initialize the DB variable and export it:
client = new MongoClient(uri, options)
dbPromise = client.connect()
let db;
dbPromise.then((value)=>{
const client = value;
db = client.db("datatbase_name");
})
.catch((error)=>{
console.error(error);
});
export default db
I totally expect this to work. However, when I import db to another file and use it, the db is null. However, I waited until the dbPromise is resolved to pass db a value.
Use await like this.
dbPromise = client.connect()
let db;
await dbPromise.then((value)=>{
const client = value;
db = client.db("datatbase_name");
})
.catch(error){
console.error(error);
}
export default db
because mongoose is asynchronous so we have to use await before dbPromise otherwise export will be executed first before dbPromise.
Try this, instead of returning db, return an async function, which you can all with await, in other parts to obtain, the connection to the database, the function will not try to make repeated connections, if they are already present:
let db, connection;
async function dbSetup() {
try {
if(!connection) {
connection = await client.connect();
}
if(!db) {
db = await connection.db("datatbase_name");
}
return db;
} catch(error){
console.error(error);
}
}
export default dbSetup;
Another way is if you have node version 14.8 or greater, you can use top-level await functionality, which is basically using await, not inside an async function, like this:
client = new MongoClient(uri, options);
dbPromise = await client.connect();
let db = await dbPromise.db("datatbase_name");
export default db;
I am building a discord bot, and I'm trying to connect it to a mongo DB.
The way my code is structured, I have a 'main' file, called index.js, where I run my main code, on the main code, I handle the events. Inside the event 'on ready'(which is executed once) I connect to the DB. This is how I handle the events on index.js:
for (const file of eventFiles) {
const event = require(`./events/${file}`);
if (event.once) {
client.once(event.name, (...args) => event.execute(...args, commands));
} else {
client.on(event.name, (...args) => event.execute(...args, commands));
}
}
To connect to the DB, I have an event script, called ready, that is called only once. The problem I'm having is, when I try to connect to the DB, I get stuck without a response. I'm using mongoose js and following their documentation to connect. Their documentation states that I need to use an async function to connect.
When I do that, the code gets 'stuck'. If I remove the async and await statement form the code below, it works. It would be ok to use it like that, but that's not a good pratice. Code fore ready.js follows:
const mongoose = require('mongoose')
require('dotenv').config()
const testSchema = require('../test-schema')
module.exports = {
name: 'ready',
once: true,
async execute(client, commands) {
console.log(`Ready! Logged in as ${client.user.tag}`);
await mongoose.connect(process.env.MONGO_URI);
console.log("Database Connected!");
},
};
So, is it ok to just remove the async and await?
Thanks in advance.
Disclaimer: English is not my first language, sorry if it sounds confuse.
So, I figured it out (sort of).
Changed my code to the following, and it worked:
const mongoose = require('mongoose')
require('dotenv').config()
module.exports = {
name: 'ready',
once: true,
async execute(client, commands) {
console.log(`Ready! Logged in as ${client.user.tag}`);
main().catch(err => console.log(err));
console.log("Database Connected!");
},
};
async function main() {
await mongoose.connect(process.env.MONGO_URI);
}
Basically, put the connection inside the main function, and called it on the execute method.
It worked.
I have created a saperate js file in node js and I am trying to connect to postgres sql using below code but it never worked. always promise is pending. code is not waiting at this line (await client.connect()). I Could not understand what the issue is. can any one please help me on this.
const pg = require('pg');
async function PostgresConnection(query,config) {
const client = new pg.Client(config);
await client.connect(); //not waiting for the connection to succeed and returning to caller and exit
const pgData = await client.query(query);
await client.end();
return pgData;
}
async function uploadDataToPostgres(config) {
var query="select * from firm_data";
await PostgresConnection(query, config);
}
module.exports = {
uploadDataToPostgres
}
I am trying to call above method from other page
function ProcessData()
{
var result = uploadDataToPostgres(config);
}
When you invoke an async function from outside an async function, you need to treat it as a Promise. Change your invoker function to look like this:
function ProcessData() {
uploadDataToPostgres(config)
.then(function success(result) {
/* do something useful with your result */
console.log(result)
})
.catch(function error(err) {
console.error('uploadDataToPostgres failure', err)
})
}
Your code, var result = uploadDataToPostgres(config), stashes a Promise object in result. But the code behind the promise (the code in your async function) doesn't run until you invoke .then() or .else() on it.
It's a bit confusing until you completely grasp the similarity between async functions and Promises: async functions are Promise functions with nice syntax.
It's possible your uploadDataToPostgres() function throws an error (failure to connect to the db?) and the .catch() will catch that.
I new to aws lambda and serverless.
Serverless provides me one file called handler.js.
How can I use the mongo database in this file?
In regular nodejs application I was connect to the mongo database then after the connection is good I was continue the application and launch the server. something like this:
(async() => {
await mongoose.connect(...);
const app = import('./app');
app.listen(....);
})();
But when I use serverless the application already launched. when to make the connection to db should be?
Create sperate mongoconnection.js to maintain mongo db connection and import it in handler.js
mongoconnection.js
"use strict";
// Import dependency.
const { MongoClient } = require('mongodb');
// Connection string to the database
const uri = process.env.MONGODB_URI;
// Validate that the database connection string has been configured.
if (!uri) {
throw new Error(
'The MONGODB_URI environment variable must be configured with the connection string ' +
'to the database.'
);
}
// Cached connection promise
let cachedPromise = null;
// Function for connecting to MongoDB, returning a new or cached database connection
module.exports.connectToDatabase = async function connectToDatabase() {
if (!cachedPromise) {
// If no connection promise is cached, create a new one. We cache the promise instead
// of the connection itself to prevent race conditions where connect is called more than
// once. The promise will resolve only once.
// Node.js driver docs can be found at http://mongodb.github.io/node-mongodb-native/.
cachedPromise =
MongoClient.connect(uri, { useNewUrlParser: true, useUnifiedTopology: true });
}
// await on the promise. This resolves only once.
const client = await cachedPromise;
return client;
}
handler.js
// Import dependency.
const { connectToDatabase } = require('./connect-to-mongodb');
// Handler
module.exports.handler = async function(event, context) {
// Get a MongoClient.
const client = await connectToDatabase();
// Use the connection to return the name of the connected database.
return client.db().databaseName;
}
Please refer below link for more details
https://docs.atlas.mongodb.com/best-practices-connecting-to-aws-lambda/
I was wondering what I'm doing wrong here.I couldn't connect to the server and gives me a message that a promise was rejected and was not handled by catch(). Am i missing an async function somewhere? Thanks in advance.
const mongoose = require("mongoose");
const Dishes = require("./models/dishes");
const url = "mongodb://localhost:27017/conFusion";
const connect = mongoose.connect(url);
mongoose.set("useUnifiedTopology", true);
mongoose.set("useNewUrlParser", true);
connect.then(db => {
console.log("Connected correctly to server");
var newDish = Dishes({
name: "Uthappizza",
description: "test"
});
newDish
.save()
.then(dish => {
console.log(dish);
return Dishes.find({});
})
.then(dishes => {
console.log(dishes);
return Dishes.remove({});
})
.then(() => {
return mongoose.connection.close();
})
.catch(err => {
console.log(err);
});
});
You have no rejection handler on the promise from mongoose.connect itself (your connect constant). you only use then, not catch, and you don't supply the second argument to then.
So the minimum change is:
connect.then(db => {
// ...
})
.catch(error => { // ***
// ...handle/report error connecting... // ***
}); // ***
Am i missing an async function somewhere?
No, but using one might make the code easier to follow (this is subjective). The purpose of async/await is to make it possible to write code with our usual flow-control structures while using promises.
For instance, if you can't use top-level await or you don't want to, you could wrap all your code in an immediately-invoked async function like this:
const mongoose = require("mongoose");
const Dishes = require("./models/dishes");
const url = "mongodb://localhost:27017/conFusion";
// If you can't use top level `await`, you can use an `async` IIFE
(async () => {
const connect = await mongoose.connect(url);
mongoose.set("useUnifiedTopology", true);
mongoose.set("useNewUrlParser", true);
console.log("Connected correctly to server");
var newDish = Dishes({
name: "Uthappizza",
description: "test"
});
const dish = await newDish.save();
console.log(dish);
const dishes = await Dishes.find({});
console.log(dishes);
await Dishes.remove({});
await mongoose.connection.close();
})().catch(error => {
// ...handle/report error...
});
If you can use top-level await and you want to (it does mean you have to switch to using JavaScript's own module syntax instead of CJS modules, but IMHO that's a good thing anyway), you can do this:
import mongoose from "mongoose";
import Dishes from "./models/dishes.js";
const url = "mongodb://localhost:27017/conFusion";
try {
const connect = await mongoose.connect(url);
mongoose.set("useUnifiedTopology", true);
mongoose.set("useNewUrlParser", true);
console.log("Connected correctly to server");
var newDish = Dishes({
name: "Uthappizza",
description: "test"
});
const dish = await newDish.save();
console.log(dish);
const dishes = await Dishes.find({});
console.log(dishes);
await Dishes.remove({});
await mongoose.connection.close();
} catch (error) {
// ...handle/report error...
}
Note, though, that you'd probably only want to do that in your top-level module (which it looks like this is), since it holds up resolution of the module tree. That's fine for the entry point module, or a module that can't create its exports until a promise settles, but for the logic in the code you've shown it would probably only be appropriate in the entry point module.