Firebase - push() callback - callback

Is there any way how to find out when my data were saved in DB using push() method? I wrote following code but it saves data multiple times...
db.ref('news').push(opts).then(() => {
// do smth. (e.g. hide preloader) when data were succesfully saved
})

If I am not wrong, push() callback should be like this:
db.ref('news').push(opts, function(error) {
if (error)
console.log('Error has occured during saving process')
else
console.log("Data hss been saved succesfully")
})

Related

How mongoose middleware works and what is next()?

userSchema.pre('save',async function(next){
//hash the password before saving user to database
next()
})
Hey guys I'm trying to understand the concept of middleware in mongoose. Assuming that I have an userSchema that I run the pre hook on to hash the password before saving the user to the database. On the surface, as far as I understand, the above code that I have will hash the password (not the important part for this question) and then call next() to signal that the function is done. However, I am trying to understand how things work under the hood. I want to know what is next() ? Can you guys walk me through an example of how everything works together under the hood from start to end once the code get executed or somehow help me to have a better understanding of this concept? Thanks
Short : with the pre method you can register listeners for certain events of your Schemas. So pre('save', callback) will fire whenever you save a document of said Model. pre means it will execute before the event, so it can be used (for example) to hash a password before saving it to the document.
However, you have several options to define them, see below :
The combination of using an async callback function and providing the next parameter is not necessary, you can either :
use normal callback with next parameter
the next parameter is a function provided to you by mongoose to have a way out, or to tell mongoose you are done and to continue with the next step in the execution chain. Also it is possible to pass an Error to next it will stop the execution chain.
schema.pre('save', function(next) {
// do stuff
if (error) { return next(new Error("something went wrong"); }
return next(null);
});
use async callback
Here the execution chain will continue once your async callback has finished. If there is an error and you want to break/stop execution chain you just throw it
schema.pre('save', async function() {
// do stuff
await doStuff()
await doMoreStuff()
if (error) { throw new Error("something went wrong"); }
return;
});
Straight from the docs : https://mongoosejs.com/docs/middleware.html#pre
Example
const { Schema, model } = require('mongoose');
const SomeSchema = new Schema ({
name : { type : String }
});
SomeSchema.pre('save', function (next) {
console.log('pre save fired!');
return next();
});
const Some = model('Some', SomeSchema);
console.log('before create');
const doc = new Some({ name : 'test' });
doc.save((err) => {
console.log('after saved');
});
This will output
before create
pre save fired!
after saved

Using .catch with async/await

I am wondering if I can still use .catch() within an async function to catch the error instead of using a try-catch block.
The following code is from my project using MongoDB and Express:
router.get('/communities', EnsureAuthenticated, async (req, res) =>{
//Look up the user in the db + populate the community field
const userInfo = await User_DB
.findOne({ _id:req.user._id, })
.populate('communities')
.lean()
.catch(err => {
console.log(err)
res.status(500)
.json({
msg: 'DB: Error Fetching User Info',
});
// rest of the functions that take userInfo as the input
});
When using try-catch all variables will be limited to within the scope of that try-catch block.
If I need to use the userInfo as the input for other functions down the line I'll have to put everything within that try-catch block which doesn't look clean and can be confusing. Because you don't know which function does the error belongs to if there is any.
Is my understanding correct?
I apologize for the formatting. I'm doing this on my phone.
You can also make a central error handler, you can find an example here

How to Catch Error When Data is not Sent on Angularfire when adding data to firebase?

Im using angularfire to save data into my firebase. Here is a quick code.
$scope.users.$add({
Name:$scope.username,
Age:$scope.newage,
Contact: $scope.newcontact,
});
alert('Saved to firebase');
I am successful in sending these data to my firebase however how can I catch an error if these data are not saved successfully? Any ideas?
EDIT
So after implementing then() function.
$scope.users.$add({
Name:'Frank',
Age:'20',
Contact: $scope.newcontact,
}).then(function(ref) {
alert('Saved.');
}).catch(function(error) {
console.error(error); //or
console.log(error);
alert('Not Saved.');
});
When connected to the internet. The then() function is fine. It waits for those data to be saved in firebase before showing the alert.
What I want is for it to tell me that data is not saved. catch error function is not firing when i am turning off my internet connection and submitting those data.
When you call $add() it returns a promise. To detect when the data was saved, implement then(). To detect when saving failed, implement catch():
var list = $firebaseArray(ref);
list.$add({ foo: "bar" }).then(function(ref) {
var id = ref.key;
console.log("added record with id " + id);
list.$indexFor(id); // returns location in the array
}).catch(function(error) {
console.error(error);
});
See the documentation for add().
Update
To detect when the data cannot be saved due to not having a network connection is a very different problem when it comes to the Firebase Database. Not being able to save in this case is not an error, but merely a temporary condition. This condition doesn't apply just to this set() operation, but to all read/write operation. For this reason, you should handle it more globally, by detecting connection state:
var connectedRef = firebase.database().ref(".info/connected");
connectedRef.on("value", function(snap) {
if (snap.val() === true) {
alert("connected");
} else {
alert("not connected");
}
});
By listening to .info/connected your code can know that the user is not connected to the Firebase Database and handle it according to your app's needs.

Error handling with Mongoose

I am an absolute NodeJS beginner and want to create a simple REST-Webservice with Express and Mongoose.
Whats the best practice to handle errors of Mongoose in one central place?
When anywhere an database error occurs I want to return a Http-500-Error-Page with an error message:
if(error) {
res.writeHead(500, {'Content-Type': 'application/json'});
res.write('{error: "' + error + '"}');
res.end();
}
In the old tutorial http://blog-next-stage.learnboost.com/mongoose/ I read about an global error listener:
Mongoose.addListener('error',function(errObj,scope_of_error));
But this doesn't seem to work and I cannot find something in the official Mongoose documentation about this listener. Have I check for errors after every Mongo request?
If you're using Express, errors are typically handled either directly in your route or within an api built on top of mongoose, forwarding the error along to next.
app.get('/tickets', function (req, res, next) {
PlaneTickets.find({}, function (err, tickets) {
if (err) return next(err);
// or if no tickets are found maybe
if (0 === tickets.length) return next(new NotFoundError));
...
})
})
The NotFoundError could be sniffed in your error handler middleware to provide customized messaging.
Some abstraction is possible but you'll still require access to the next method in order to pass the error down the route chain.
PlaneTickets.search(term, next, function (tickets) {
// i don't like this b/c it hides whats going on and changes the (err, result) callback convention of node
})
As for centrally handling mongoose errors, theres not really one place to handle em all. Errors can be handled at several different levels:
connection errors are emitted on the connection your models are using, so
mongoose.connect(..);
mongoose.connection.on('error', handler);
// or if using separate connections
var conn = mongoose.createConnection(..);
conn.on('error', handler);
For typical queries/updates/removes the error is passed to your callback.
PlaneTickets.find({..}, function (err, tickets) {
if (err) ...
If you don't pass a callback the error is emitted on the Model if you are listening for it:
PlaneTickets.on('error', handler); // note the loss of access to the `next` method from the request!
ticket.save(); // no callback passed
If you do not pass a callback and are not listening to errors at the model level they will be emitted on the models connection.
The key take-away here is that you want access to next somehow to pass the error along.
hey this is the simplest way i found..
try { } catch (error) {
console.log(error);
// checking validation
if (error.name === "ValidationError") {
const message = Object.values(error.errors).map(value => value.message);
return res.status(400).json({
error: message
})
}
res.status(400).json(error.message)
}
}
just copy paste

How to execute a stored function from mongodb-native/node.js

I'm trying to execute a stored function from mongodb-native/node.js environment.
I have several functions inside db.system.js.
It seems Db.executeCommand() is the function but I have no idea how can I pass the function name and the arguments.
I tried db.eval() as suggested but I got the following.
> db.eval('getValue()', {}, function(er,doc) {console.log(er);console.log(doc);});
{ stack: [Getter/Setter], arguments: [ 'send', undefined ], type: 'non_object_property_call', message: [Getter/Setter] }
null
getValue is a simple function that returns an integer.
Anyone has an idea? Thanks.
Assuming db is your open database handler:
db.eval("myFunction(param, param_n)", function(error, result) { });
Looks like you can pass the parameters in separately, too. https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/db.js
There you go:
function testDB(req,res) {
MongoClient.connect(url, function(err, db) {
if (err) {
console.log(err);
res.send('connection failed');
} else {
db.eval("testFunction()", function(err, output) {
if(err){
console.log("ERROR: "+err);
res.send(err);
return;
}else{
res.send(output);
return;
}
});
db.close();
}
});
}
I am assuming that you call it for a rest API.
You can change the function params based on your need.
Also I assume your URL has enough permissions to call the function.
If not, use a mongo tool like RoboMongo and change the permission to the user.
It's because you are thinking it will return value , This is asynchronous call , you must pass a callback function with (err,doc) to get the return value
db.eval('addNumbers(4,5)',function(er,doc){
console.log(doc);
})