Reputation: 2584
I'm looking for advice on how to chain promises for a "find or create" feature using mongodb/mongoose
.
I've currently tried:
userSchema.statics.findByFacebookIdOrCreate = function(facebookId, name, email) {
var self = this;
return this.findOne({
facebookId: facebookId
}).exec().then(function(user) {
if (!user) {
return self.model.create({
facebookId: facebookId,
name: name,
email: email
}).exec().then(function(user) {
return user;
});
}
return user;
});
};
And I call it from my (node/express) API endpoint:
User.model.findByFacebookIdOrCreate(fbRes.id, fbRes.name, fbRes.email)
.then(function(user) {
return res.sendStatus(200).send(createTokenForUser(user));
}, function(err) {
return res.sendStatus(500).send({
error: err
});
});
Problems are though:
Can anyone see what I'm doing wrong, and how I could do it better?
Thanks.
UPDATE
The cause of the problem was that
self.model.create(...)
should have been (no model reference)
self.create(...)
However, I now need to know what I'm doing wrong with the error handling - I could see that an error was occurring, but I couldn't see the cause.
I still have some errors occurring which I know because I get a status of 500
return res.sendStatus(500).send({ error: err });
but the actual error message/detail is empty.
Upvotes: 5
Views: 2712
Reputation: 5318
Your question (and the subsequent answer from @EduardoRodríguez) helped me solve a similar problem, so cheers! However, using latest mongoose version + ES6 destructuring and arrow functions, I was able to get it down to something akin to the following:
userSchema.statics.findByFacebookIdOrCreate = function (facebookId, name, email) {
var User = this;
return User.findOne({facebookId})
.then(user => user || User.create({facebookId, name, email}));
};
...and then:
User.findByFacebookIdOrCreate(fbRes.id, fbRes.name, fbRes.email)
.then(user => res.sendStatus(200).send(createTokenForUser(user))
.catch(error => res.sendStatus(500).send({error});
Note: this does involve using native ES6 promises by configuring mongoose with:
mongoose.Promise = global.Promise;
I'm still quite new to this, but hopefully this helps others going forward (it works for me).
Upvotes: 0
Reputation: 172
The problem could be that:
This will always returns a promise, it allows you to use then() after your method (You will have to add mpromise module):
userSchema.statics.findByFacebookIdOrCreate = function (facebookId, name, email) {
var self = this;
var Promise = require('mpromise');
var promise = new Promise;
this.findOne({facebookId: facebookId }).exec()
.then(function (user) {
if(user) {
promise.fulfill(user);
return;
}
self.model.create({ facebookId: facebookId, name: name, email: email })
.then(function (user) {
promise.fulfill(user);
return;
});
});
return promise;
};
Hope this helps you
Upvotes: 2