I recommend this webpage http://www.promisejs.org/ if you are starting with promises. I don't pretend to cover promises basics in this post.
Promises are a very simple but I had some problems at the beginning with a real life example. I only found very simple promises examples.
For this example we are going to use the Q library (https://github.com/kriskowal/q). In that page there are many examples on how to use the library.
We're also using Mongoose to save a client to the database.
For this example, the client id must be unique.
This is the client schema (client-model.js):
module.exports = function(app, mongoose){
var Schema = mongoose.Schema;
var client = new Schema({
id: String,
name: String,
lastName: String,
gender: String
});
return mongoose.model('Client', client);
};
And this is the function that saves the client. We will validate an empty or repeated ID, empty name or empty lastName (this can be validated by Mongoose with required and unique, but for this example we'll do it manually)
var Q = require('q'),
mongoose = require('mongoose');
module.exports = function(app) {
var clientModel = require('../models/client-model.js')(app, mongoose);
var isNotEmptyOrNull = function(pValue) {
if (!pValue) {
return false;
} else if (pValue.length < 1) {
return false;
}
return true;
};
app.post('/api/client', function(pRequest, pResponse) {
// Validate empty id, name and lastName
Q.all([
isNotEmptyOrNull(pRequest.body.id),
isNotEmptyOrNull(pRequest.body.name),
isNotEmptyOrNull(pRequest.body.lastName)
])
.then(function(pResults) {
// pResults is an array with the result of each function. In this case, we expect it to be [true, true, true]
var findClient = Q.nbind(clientModel.find, clientModel);
// Check if id, name and lastName is not null or empty
var isValidObject = pResults.every(function(pResult) {
return pResult;
});
if (!isValidObject) {
// It's not a valid object, we send a bad request to the user
throw 'Id, name and lastName are required';
}
return findClient({ id: pRequest.body.id});
})
.then(function(pFoundClient) {
// The id already exists
if (pFoundClient && pFoundClient.length > 0) {
throw 'Id must be unique';
}
// Everything is ok, we save the client
var clientToSave = new clientModel(pRequest.body);
return Q.when(clientToSave.save());
})
.then(function() {
return pResponse.send('Client saved');
})
.catch(function(pError) {
// Catch any error
console.log(pError);
return pResponse.send(400, pError);
});
});
};
This is the explanation on Q.all from the Q API reference:
Returns a promise that is fulfilled with an array containing the fulfillment value of each promise, or is rejected with the same rejection reason as the first promise to be rejected. This method is often used in its static form on arrays of promises, in order to execute a number of operations concurrently and be notified when they all succeedAnd this is nbind:
Creates a promise-returning function from a Node.js-style method, optionally binding it with the given variadic arguments.With that example it should be clear how to use Q Promises and Mongoose to save the object. Please leave questions, comments or feedback. Thanks