首页 > 解决方案 > How to handle multithreading in database in nodejs?

问题描述

I have problems using the database in nodejs with mongodb. Specifically when I use findOne in the data loop. The result is that outp returns an empty value. Thanks everyone!

var room_members = cdb.get().collection('room_members');
var historys = cdb.get().collection('history');
var outp = [];
room_members.find({id_account: ObjectId(deToken._id)}).toArray(function (f_err, f_res) {
    for (var i = 0; i < f_res.length;i++) {
        historys.findOne({
            id_room: ObjectId(f_res[i].id_room)
            }, function (h_err, h_res) {
            if (h_res) {
                outp.push(h_res);
            }
            })
        }
        res.json({
        status: ok,
        message: outp
        });
});

标签: node.jsmongodb

解决方案


As you're pushing element in outp array in the callback of historys.findOne, and historys.findOne doesn't block the thread, ie node won't wait for it to finish to continue execution, the callback isn't called when you call res.json.

var room_members = cdb.get().collection('room_members');
var historys = cdb.get().collection('history');
var outp = [];
room_members.find({id_account: ObjectId(deToken._id)}).toArray(function (f_err, f_res) {
    for (var i = 0; i < f_res.length;i++) {
        historys.findOne({
            id_room: ObjectId(f_res[i].id_room)
            }, function (h_err, h_res) {
            if (h_res) {
                outp.push(h_res);
            }
            })
        }
        res.json({
        status: ok,
        message: outp
        });
});

If you're using this library, if you don't pass a callback, you get a promise, so you can do like this :

var room_members = cdb.get().collection('room_members');
var historys = cdb.get().collection('history');
room_members.find({id_account: ObjectId(deToken._id)}).toArray(function (f_err, f_res) {
    var promises = []
    for (var i = 0; i < f_res.length;i++) {
        promises.push(historys.findOne({
            id_room: ObjectId(f_res[i].id_room)
            }))
        }
    Promise.all(promises).then(function(output){
        res.json({
        status: ok,
        message: output
        });
     }).catch(function(err){
        // Handle the error here
      })
 )


});

And if you want to use async/await:

async function get_room_members_history(req, res) {
      try {
        // Do what you want to get you're deToken using req or whatever you want
        var room_members = cdb.get().collection("room_members");
        var historys = cdb.get().collection("history");
        var rooms_members_array = await room_members
          .find({ id_account: ObjectId(deToken._id) })
          .toArray();
        var promises = [];
        for (var i = 0; i < rooms_members_array.length; i++) {
          promises.push(
            historys.findOne({
              id_room: ObjectId(rooms_members_array[i].id_room)
            })
          );
        }
        var output = await Promise.all(promises);
        res.json({
          status: ok,
          message: output
        });
      } catch (error) {
        // Handle error here
      }
    }

推荐阅读