Playing with Promises

using Bluebird

var helloTimeout = function(name, timeout, cancel){

   return new Promise(function(resolve, reject){
      setTimeout(function(){
         console.log(name);
         if(cancel){
            reject("cancelled");
         }
         else{
            resolve(name);
         }
      }, timeout || 1000);
   });
};

Wait for all

var users = [
   { name: "Juan", timeout: "3000", cancel: true },
   { name: "Valentina", timeout: "2000" },
   { name: "Julian", timeout: "5000", cancel: true }
];
var errors = [];
Promise.all([
   helloTimeout("juan", 2000, true),
   helloTimeout("valentina", 1000),
   helloTimeout("julian", 3000, true)
].map(function(promise) {
   return promise.catch(function(error){
      errors.push(error);
   }).reflect();
})).then(function(){
   console.log("end");
   console.log("errors:");
   console.log(errors);
});

Or more simple =>

var errors = [];
Promise.map(users, function(user){
   return helloTimeout(user.name, user.timeout, user.cancel).catch(function(error){
       errors.push(error);
   });
}).then(function(){
   console.log("end");
   console.log("errors:");
   console.log(errors);
});

Also with .map you can define concurrency! :o

Promise.map(users, function(user){

}, {concurrency: 2});

In Series...

Promise.mapSeries(users, function(user){
   return helloTimeout(user.name, user.timeout, user.cancel);
}).catch(function(err){

   console.log(err);
});

Processing each one of the properties of an object...

var users = {
   user1: {},
   user2: {},
   user3: {}
};
Promise.map(Object.keys(users), function(key){
    return User.create(users[key]);
});

Support Callbacks and Promises with your libraries

/*
 * @param {function(error, result)} cb - A callback to run.
 */
function foo(x, y, cb) {
    return new Promise((resolve, reject) => {
        request(..., (err, data) => {
            if(err) {
                if(cb) { cb(err); }
                reject(err);
            }
            else{
                if(cb) { cb(null, result); }
                resolve(data);
            }
        })
    });
}