Mohideen Imran Khan
Mohideen Imran Khan

Reputation: 833

Unexpected behaviour of NodeJS array

I am currently learning how to use NodeJS and wrote this relatively simple function to run at a fixed interval. The aim of this function is to retrieve newly created Droplets and update their IP addresses.

router.newDroplets = setInterval(function() {

    Server.find().then(function(svrs) {
        for (var i = 0; i < svrs.length; i++) {
            if (svrs[i].status == "Creating") {
                library.getDropletById(svrs[i].serverid).then(function(svr) {
                    if (svr.droplet) {
                        for (var j = 0; j < svr.droplet.networks.v4.length; j++) {
                            if(svr.droplet.networks.v4[j].type == 'public') {
                                var ip_address = svr.droplet.networks.v4[j].ip_address;
                                console.log(ip_address);

                                Server.update({serverid: svr.droplet.id}, {ipaddress: ip_address, status: "Online"}, function(error, n) {
                                    if (error) console.log(error);
                                    else console.log(n);
                                });
                            }
                        }
                    } else if (svr.id) {
                        // NOTE THIS LINE
                        console.log(svrs);
                    }

                }, function() {

                });
            }
        }
    }, function() {

    });

}, 2500);

The peculiar behaviour is with the line marked above.

When I use console.log(svrs), I get an array of JSON documents in the Server collection in my MongoDB. However, when I use console.log(svrs[i]), undefined is logged in the console. This happens even if I declare var i = 0; outside the for loop. Why is this happening and how can I access svrs[i]?

Upvotes: 0

Views: 74

Answers (1)

Vadim
Vadim

Reputation: 17957

The way promises work is that the promise chains run asynchronously. By the time that code runs, i is equal to svrs.length, so svrs[i] will be undefined. That's because the for loop executes in its entirety before any of the then callbacks are called. You could convert your code to use Array.prototype.forEach

So you can try something like

svrs.forEach(function(svrInstance, i) {
  if (svrInstance.status == "Creating") {
    library.getDropletById(svrInstance.serverid).then(function(svr) {
      if (svr.droplet) {
        ...
      } else if (svr.id) {
        console.log(svrs[i]);
      }
     });
   }
});

Upvotes: 2

Related Questions