1

I have a problem with the asynchrony of nodejs. Hope you can help me.

exports.DeviceInfo = function(req, res, next) {
  var nets = req.body.networks;

  db.collection("device", function(err, deviceConf) {
    var detected_beacons = [];

    if (!err) {
      for (var i = 0; i < nets.length; i++) {
        deviceConf
          .find({
            "data.number": nets[i]
          })
          .toArray(function(errFind, saver) {
            if (!errFind && saver) {
              saver.forEach(function(disp) {
                var detected = {};
                detected.address = disp.address;
                detected_beacons.push(detected);
                console.log(detected_beacons);
              });
            }
          });
      }
      console.log(detected_beacons);
      res.json(detected_beacons);
    } else {
      console.error(err);
      res.status(500);
      res.json({
        message: "Couldn't connect to database"
      });
    }
  });
};

If I write some logs, we could see which is the problem. The detected_beacons is being returned before the for clause. I want to be returned after for in order to be full of data. I have read about callbacks and promises but I don't know how to use them in my code.

image

Niezborala
  • 1,857
  • 1
  • 18
  • 27
aserrin55
  • 350
  • 5
  • 15

2 Answers2

1

Try this code. you cannot do a for loop concerning callback functions.

exports.DeviceInfo= function(req,res,next){
var nets = req.body.networks;
db.collection("device", function(err, deviceConf){
    var detected_beacons = [];
    var netSize = nets.length;
    var beaconsLoop = function(i) {
        deviceConf.find({"data.number" : nets[i]}).toArray(function(errFind, saver){
                if (!errFind && saver){
                    var saverSize = saver.length;
                    saver.forEach(function(disp){
                        var detected = {};
                        detected.address = disp.address;
                        detected_beacons.push(detected);
                        saverSize--;
                        if (saverSize == 0) {
                            if (i != netSize - 1) {
                                i++;
                                beaconsLoop(i);
                            } else {
                                res.json(detected_beacons);
                            }
                        }
                    });
                }
            });
    };

    if (!err){
        if (netSize > 0) beaconsLoop(0);
    } else {
        console.error(err);
        res.status(500);
        res.json({message:"Couldn't connect to database"});
    }
});

};

Ediruth
  • 168
  • 1
  • 7
  • There was an option not contempled, if the saver empty. Correcting that repeating `if (i != netSize - 1) { i++; beaconsLoop(i); } else { res.json(detected_beacons); }` . Your solution was fantastic. Thanks! – aserrin55 Sep 02 '16 at 12:54
0

I made a simple solution using map:

if (!errFind && saver) {
  var detected_beacons = saver.map(function(disp) {
    return {
      address: disp.address
    };
  });

  console.log(detected_beacons);
  res.json(detected_beacons);
}

Here is full code.

Niezborala
  • 1,857
  • 1
  • 18
  • 27
  • This is also valid but it does not solve the asynchrony issue @Nie, the detected_beacons continue to be sent first and empty. – aserrin55 Sep 02 '16 at 11:24