Node JS Promises, Practical uses

In last article I discussed the node js callback & native (es6) promises.

Their are more cases where promises come handy.

Let a case where we need to get a user information for given id, but information is in different sql tables/mongo collections.

// As promise passed resolved object into chain, So we need to use that one

getUserInfo(userId) {
  // Return Promised Info
  return userModel.findOne({_id: userId}).exec();
}
getUserAddressInfo(preResults) {
  // Return Promised having info merged with preResults 
  return userAddrModel.findOne({_id: preResults._id}).exec().then((results) => {
   return [preResults, results]
  });
}
getUserExperienceInfo(preResults) {
  // Return Promised having info merged with preResults 
  return userExpModel.findOne({_id: preResults._id}).exec().then((results) => {
   return [preResults, results]
 });
}

getUserEducationInfo(preResults) {
 // Return Promised having info merged with preResults 
 return userEduModel.findOne({_id: preResults._id}).exec().then((results) => {
   return [preResults, results]
 });
}

getUserInfo(userId)
 .then(getUserAddressInfo)
 .then(getUserExperienceInfo)
 .then(getUserEducationInfo)
 .then((results) => {
    console.log(results)
 }).catch(err => {
    console.error('Getting error')
 });

Chain approach in last article is not very effective as that will block the node js event model which reduce performance.

We need parallel execution of functions but still need their output at final place. We need to change our code some thing like that

getUserInfo(userId) {
  return userModel.findOne({_id: userId}).exec();
}
getUserAddressInfo(userId) {
  return userAddrModel.findOne({_id: userId}).exec();
}
getUserExperienceInfo(userId) {
  return userExpModel.findOne({_id: userId}).exec();
}

getUserEducationInfo(userId) {
  return userEduModel.findOne({_id: userId}).exec();
}

NOTE : exec is Mongoose API function for return promised data.

Promise.all([
  getUserInfo(userId), 
  getUserAddressInfo(userId), 
  getUserExperienceInfo(userId),
  getUserEducationInfo(userId)
]).then((results) => {
  console.log(results)
}).catch(err => {
  console.error('Getting error')
});

Here all functions called parallel by Promise.all api method in iterator (array) way. Result would be an array where first element return the result of getUserInfo, second on getUserAddressInfo and so on…

If we need to apply function to an array’s all values, We can still use promises using map (or other you prefer). Let we need some user profile content from public url for group of users in array.

const promises = userIds.map((userId) => {
 return new Promise((resolve, reject) => {
   http.get('http://www.example.com/user' + userId, function(response) {
     resolve(response);
   }); 
 }); 
});

Promise.all(promises).then((results) => {
  console.log(results);
}).catch(err => {
  console.error(err);
});

Other promise api function than Promise.all is Promise.race which return the first function who completed its execution.

Promise.all([
  getSite1Feeds(), 
  getSite2Feeds(), 
  getSite3Feeds(), 
  getSite4Feeds(), 
]).then((results) => {
  console.log(results); // Whoever comes first
}).catch(err => {
  console.error('Getting error')
});

Mozilla Promises API Documentation

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *