无法检索数据并推送节点js中的内部循环

时间:2018-02-05 08:52:24

标签: node.js mongodb asynchronous async-await

我正在尝试检索出勤列表以及用户详细信息。 我正在使用caminte.js(http://www.camintejs.com/)Cross-db ORM进行数据库交互。 这是我的模型函数“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 });
            });
        }
    });
};

我只收到没有用户详细信息的出勤名单。如何强制将用户详细信息输入到考勤列表中?任何帮助!! 谢谢

1 个答案:

答案 0 :(得分:1)

此行为是异步的。当您向DB提出请求时,您的code keeps running, while task to get data comes to task queue. 为简单起见,您需要在处理异步作业时使用promises 从这里重写您的代码:

 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 });
        });
    }
});

对此:

 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);
     });
  })
 }

所以,现在我们可以使用这些单独的函数使异步行为看起来像同步。

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) {

}

注意:我没有测试过此代码,yu更容易使用您的实际数据并使用Promises和async / await
请记住,对db的每个请求都是异步的,您需要让代码等待这些数据。