0

I am trying to retrieve attendance list along with user details. I am using caminte.js(http://www.camintejs.com/) Cross-db ORM for database interaction. Here is my code sample of model function "attendanceList".

exports.attendanceList = function (req, callback) {
    var query = req.query;
    var searchfilters = {};
    if(!req.user){
        callback({ code:400, status:'error', message: 'Invalid Request', data:{}});
    }else{
        searchfilters["vendor_id"] = parseInt(req.user._id);
    }

    if(query.location && parseString(query.location) != '') {
        searchfilters["location"] =  parseString(query.location);
    }   

    if (query.device_details && parseString(query.device_details) != '') {
        searchfilters["device_details"] =  parseString(query.device_details);
    }

    if(query.created_on) {
        searchfilters["created_on"] = query.created_on;
    }
    if(query.status) {
        searchfilters["status"] = { regex: new RegExp(query.status.toLowerCase(), "i") };
    }
    var SkipRecord = 0;
    var PageSize = 10;
    var LimitRecord = PageSize;
    var PageIndex = 1;
    if(query.pagesize) {
        PageSize = parseInt(query.pagesize);
    }
    if(query.pageindex) {
        PageIndex = parseInt(query.pageindex);
    }
    if (PageIndex > 1) {
        SkipRecord = (PageIndex - 1) * PageSize;
    }
    LimitRecord = PageSize;
    var SortRecord = "created_on";
    if(query.sortby && query.sorttype) {
        var sortingBy = query.sortby;
        var sortingType = 'ASC';
        if(typeof query.sorttype !== 'undefined') {
            sortingType =  query.sorttype;
        }
        SortRecord = sortingBy + ' ' + sortingType;
    }

    Attendance.find({ where: searchfilters, order: SortRecord, limit: LimitRecord, skip: SkipRecord }, async function (err, result) {
        if(err){ 
            callback({ code:400, status:'error', message:'Unable to connect server', errors:err });
        } else {
            await result.map(function(row, i){
               User.findById(parseInt(row.user_id), function(err, data){
                   if(err){ 
                    console.log(err); 
                   } else { 
                    result[i]['userDetails'] = data; 
                   }
                });
            });
            await Attendance.count({ where: searchfilters }, function (err, count) {
                callback({ code:200, status:'success', message:'OK', total:count, data:result });
            });
        }
    });
};

I am getting only attendance list without user details. How do I force to push user details into attendance list? Any Help!! Thank You

1 Answer 1

1

This behavior is asynchronous. When you're making request to DB, your code keeps running, while task to get data comes to task queue.
To keep things simple, you need to use promises while handling asynchronous jobs.
Rewrite your code from this:

 Attendance.find({ where: searchfilters, order: SortRecord, limit: LimitRecord, skip: SkipRecord }, async function (err, result) {
    if(err){ 
        callback({ code:400, status:'error', message:'Unable to connect server', errors:err });
    } else {
        await result.map(function(row, i){
           User.findById(parseInt(row.user_id), function(err, data){
               if(err){ 
                console.log(err); 
               } else { 
                result[i]['userDetails'] = data; 
               }
            });
        });
        await Attendance.count({ where: searchfilters }, function (err, count) {
            callback({ code:200, status:'success', message:'OK', total:count, data:result });
        });
    }
});

To this:

 const findAttendanceFirst = (searchFilters, SortRecord, LimitRecord, SkipRecord) => {
   return new Promise((resolve, reject) => {

    Attendance.find({ where: searchFilters, order: SortRecord, limit: LimitRecord, skip: SkipRecord }, (err, result) => {
      if(err) return reject(err);
      resolve(result);
    });
   });
 }

 const findUserByIdForUserDetails = (userId) => {
   return new Promise((resolve, reject) => {
     User.findById(parseInt(userId), function(err, data){
       if(err) return reject(err);
       resolve(data);
     })
   });
 }

 const getAttendanceCount = (searchFilters) => {
  return new Promise((resolve, reject) => {
     Attendance.count({ where: searchFilters }, (err, count) => {
       if(err) return reject(err);
       resolve(count);
     });
  })
 }

So, now we can use this separate functions to make async behavior looks like sync.

try {
  const data = await findAttendanceFirst(searchFilters, SortRecord, LimitRecord, SkipRecord);

  for(let userData of data){
    try {
      userData.userDetails = await findUserByIdForUserDetails(userData.user_id);
    } catch(e) {
      // Some error happened, so no user details.
      // you can set here null or nothing to userDetails.
    }
  }
  let count;
  try {
    count = await getAttendanceCount(searchFilters);
  } catch(e){
    // Same as before.
  }

  const callBackData = { code:200, status:'success', message:'OK', total:count, data:result };

  // And here you can do whatever you want with callback data. Send to client etc. 
} catch(e) {

}

NB: I've not tested this code, it will be easier for yu to play with your actual data and use Promises and async/await
Just remember that each request to db is asynchronous, and you need to make your code wait for this data.

Sign up to request clarification or add additional context in comments.

6 Comments

Not working, var attendanceObj = await new Promise((resolve, reject) => {/*Code here*/} console.log(attendanceObj ); but I am geeting list without attendance details.
Put console.log(data) before this line result[i]['userDetails'] = data; Then check if data is ok. After that put console.log(result) before Attendance.count Debug a little and you'll see the problem
Data is fine but logging after logging result in console. I am check on debug that code is not working asynchronously.
userData.userDetails not assigning user details in data!!
@PriyabrataAtha have you tried to debug it? Adding console log and check if request return data
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.