Mongoose error on promise with save? - node.js

When i try to get promise back with save operation on instance of model. i get error: undefined is not a function
instance.save().exec().then(..)
However, if i try to get promise with model like this, then it works.
model.find(..).exec().then(..)
Is there no way to get promise for save action. Currently i just pass callback to save function. However, for the sake of consistency i'd like to do all db operations in the same manner.

Model#save returns a promise, so you should skip the .exec():
instance.save().then(...);

Something like this?
let mongooseInstance = new MongooseInstance(Obj);
return mongooseInstance
.save()
.then(savedObj => {
if (savedObj) {
savedObj.someProperty = null;
success.data = savedObj;
return Promise.resolve(success);
} else {
return Promise.reject(error);
}
});
and maybe with a catch?
mongooseInstance
.save()
.then(saved => console.log("saved", saved))
.catch(err => console.log("err while saving", err));

Related

FindOne in mongoose returns undefined

When im consoling all the data int he database using Find method, an object with Title:'day1' is present in it but when I perform findOne operation I get undefined as output.
Please help me.
Post.findOne({ Title: 'day1'}).then(function(err, result){console.log(result)});
Use the following query instead
Post.findOne({ Title: 'day1'},function(err,data)
{
if(err)
{ res.send(err)}
else if(data)
{res.send(data)}
})
It is because you mixed up callback with Promise..
If you will use Callback method you can use the following code:
Post.findOne({Title: 'day1'}, (err, data) {
if (err) {
return res.status(404).send(err); // If there is an error stop the function and throw an error
}
res.status(200).send(data) // If there is no error send the data
})
If you are going to use the promise method:
Post.findOne({Title: 'day1'})
.then(data => res.status(200).send(data)) // Send data if no errors
.catch(err => res.status(404).send(err)) // Throw an error if something happens

How to fetch by id from Firestore?

I have been trying so hard for a couple of hours but it seems so difficult for such a simple thing. i need to fetch by id from Firebase and here is the code that I am using but which is not working:
fetch_selected_restaurant = () => {
var ref = firebase.firestore().collection('restaurants').where("res_id", "==", "5").get();
}
Keep in mind that reading firestore/firebase database is an asynchronous operation.
If you want to read document by id, you have to call it like that:
var ref = firebase.firestore().collection('restaurants').doc(yourDocId).get()
If you remember, few lines above I mentioned that almost all operations with firestore are asynchronous, reading document is not an exception. After you call get() it returns Promise. I see you stored this promise in ref variable, that`s fine.
Now in order to get a result, you have to ask this promise for results. On this step you can get what you want:
ref.then(function(doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch(function(error) {
console.log("Error getting document:", error);
});

Promises seem to not be called in correct order?

I am trying to rewrite a module I wrote that seeds a MongoDB database. It was originally working fine with callbacks, but I want to move to Promises. However, the execution and results don't seem to make any sense.
There are three general functions in a Seeder object:
// functions will be renamed
Seeder.prototype.connectPromise = function (url, opts) {
return new Promise((resolve,reject) => {
try {
mongoose.connect(url, opts).then(() => {
const connected = mongoose.connection.readyState == 1
this.connected = connected
resolve(connected)
})
} catch (error) {
reject(error)
}
})
}
[...]
Seeder.prototype.seedDataPromise = function (data) {
return new Promise((resolve,reject) => {
if (!this.connected) reject(new Error('Not connected to MongoDB'))
// Stores all promises to be resolved
var promises = []
// Fetch the model via its name string from mongoose
const Model = mongoose.model(data.model)
// For each object in the 'documents' field of the main object
data.documents.forEach((item) => {
// generates a Promise for a single item insertion.
promises.push(promise(Model, item))
})
// Fulfil each Promise in parallel
Promise.all(promises).then(resolve(true)).catch((e)=>{
reject(e)
})
})
}
[...]
Seeder.prototype.disconnect = function () {
mongoose.disconnect()
this.connected = false
this.listeners.forEach((l) => {
if (l.cause == 'onDisconnect') l.effect()
})
}
There is no issue with the main logic of the code. I can get it to seed the data correctly. However, when using Promises, the database is disconnected before anything else is every done, despite the disconnect function being called .finally().
I am running these functions like this:
Seeder.addListener('onConnect', function onConnect () { console.log('Connected') })
Seeder.addListener('onDisconnect', function onDisconnect () {console.log('Disconnected')})
Seeder.connectPromise(mongoURI, options).then(
Seeder.seedDataPromise(data)
).catch((error) => { <-- I am catching the error, why is it saying its unhandled?
console.error(error)
}).finally(Seeder.disconnect())
The output is this:
Disconnected
(node:14688) UnhandledPromiseRejectionWarning: Error: Not connected to MongoDB
at Promise (C:\Users\johnn\Documents\Code\node projects\mongoose-seeder\seed.js:83:37)
which frankly doesn't make sense to me, as on the line pointed out in the stack trace I call reject(). And this rejection is handled, because I have a catch statement as shown above. Further, I can't understand why the database never even has a chance to connect, given the finally() block should be called last.
The solution was to return the Promise.all call, in addition to other suggestions.
You are passing the wrong argument to then and finally. First here:
Seeder.connectPromise(mongoURI, options).then(
Seeder.seedDataPromise(data)
)
Instead of passing a callback function to then, you actually execute the function on the spot (so without waiting for the promise to resolve and trigger the then callback -- which is not a callback).
You should do:
Seeder.connectPromise(mongoURI, options).then(
() => Seeder.seedDataPromise(data)
)
A similar error is made here:
finally(Seeder.disconnect())
It should be:
finally(() => Seeder.disconnect())
Promise Constructor Anti-Pattern
Not related to your question, but you are implementing an antipattern, by creating new promises with new Promise, when in fact you already get promises from using the mongodb API.
For instance, you do this here:
Seeder.prototype.connectPromise = function (url, opts) {
return new Promise((resolve,reject) => {
try {
mongoose.connect(url, opts).then(() => {
const connected = mongoose.connection.readyState == 1
this.connected = connected
resolve(connected)
})
} catch (error) {
reject(error)
}
})
}
But the wrapping promise, created with new is just a wrapper that adds nothing useful. Just write:
Seeder.prototype.connectPromise = function (url, opts) {
return mongoose.connect(url, opts).then(() => {
const connected = mongoose.connection.readyState == 1
this.connected = connected
return connected;
});
}
The same happens in your next prototype function. I'll leave it to you to apply a similar simplification there, so avoiding the promise constructor antipattern.
In the later edit to your question, you included this change, but you did not return a promise in that function. Add return here:
return Promise.all(promises).then(() => {
//^^^^^^
return true
}).catch(() => {
console.log(`Connected:\t${this.connected}`)
})

API Call using a Promise or Async returning a variable with the data

NB:I am new to Node.js
I would like to call a function in the current module and it perform the data pull with a promise or async function. Then be able to access the data in a variable. Once it is a variable out of the promise maybe I can store/use/investigate the data. Any help would be much appreciated.
I manged to get the code below to run but I am not really sure if it is correct? Is there a cleaner/proper way to do this? Very confused.
I have tried to write a promise but I am going in circles.
const publicClient = new CoinbasePro.PublicClient();
const coinbasePro = require('coinbase-pro')
const p = new Promise((resolve, reject) => {
yourFunction()
async function yourFunction() {
try {
const products = await publicClient.getProducts();
resolve(products);
//console.log('ArrayName', products);
return products
} catch (error) {
reject(error);
}
}
});
p.then(result => console.log('Result', result))
p.catch(err => console.log('Error', err.message));
1) I would like to be able to invoke this promise from the same module and get the data in a variable.
2) I would like to be able to invoke this promise from another module and get the data in a variable.

Node.js Promise.all when function returns nothing

How to handle multiple calls to the same function when its returning nothing. I need to wait untill all calls are finished so i can call another function.
For now I'm using Promise.all() but it doesn't seem right:
Promise.all(table_statements.map(i => insertValues(i)))
.then(function(result) {
readNodeData(session, nodes);
})
.catch(function() {
console.log(err);
})
function insertValues(statement) {
return new Promise((res, rej) => {
database.query(statement, function (err, result) {
if (err) {
rej(err)
}
else{
console.log("Daten in Tabelle geschrieben")
res(); // basically returning nothing
}
});
});
}
This writes data to a database in multiple statements, i need to wait untill all are finished.
Is this actually the "right" way to do it? I mean... it works, but i have the feeling it's not how you are supposed to do it.
Using Promise.all for your case is a good call, since it returns a Promise, when all the promises passed as an iterable are resolved. See the docs.
However, for brevity and readability, try converting your insertValues into async-await function as follows. This tutorial would be a great place to start learning about async functions in JavaScript.
// async insertValues function - for re-usability (and perhaps easy unit testing),
// I've passed the database as an argument to the function
async function insertValues(database, statement) {
try {
await database.query(statement);
} catch (error) {
console.error(error);
}
}
// using the insertValues() function
async function updateDatabase(database) {
try {
// I am using 'await' here to get the resolved value.
// I'm not sure this is the direction you want to take.
const results = await Promise.all(
tableStatements.map(statement => insertValues(database, statement))
);
// do stuff with 'results'.. I'm just going to log them to the console
console.log(results);
} catch (error) {
console.error(error);
}
}
Here, insertValues() function doesn't return any value. Its operation on the database is entirely dependent on the query statement passed to it. I wrapped it within a try-catch block so as to catch any errors that might arise while performing the operation (s) above. More details on handling errors using try-catch can be found here.
Your promisified write to database looks ok, so we can update code from another part.
Let's rewrite it a little to use async/await and try/catch.
(async() => {
const promisifiedStatements = table_statements.map(i => insertValues(i));
try {
await Promise.all(promisifiedStatements);
readNodeData(session, nodes);
} catch(e){
console.log(e)
}
})();
I use here IIFE to use await behaviour.

Resources