Ad

Node- Promisify A Function That Contains A Loop

- 1 answer

I am using an npm package called arp-a which returns a list of network addresses.

From the brief docs, the arp.table() method looks like this:

arp.table(function(err, entry) {
  //console.log(entry) - 'entry' is an object like {ip: 192.168.0.1, mac: ff:ff:ff:ff:ff}
}

The arp.table() method evidently contains a loop and returns the arp table object by object, rather than returning an array of the objects.

I could return an array like this:

arp_table = []
arp.table(function(err, entry) {
  arp_array.push(entry)
}

But how can I 'await' the array (so that I can .map() it)?

I have tried to 'promisify' the arp.table() method using util.promisify, but then it only iterates once:

// THIS DOES NOT WORK
const util = require("util");
const arp_table = util.promisify(arp.table);
arp_table()
.then(r => console.log(x))

I have also tried putting the arp.table() method into a function with a promise, but this also does not work - returning the array before the table loops are complete:

// THIS DOES NOT WORK, EITHER
const arp_table = function() {
  var arp_array = [];
  return new Promise(resolve => {
    arp.table((err, entry) => {
      arp_array.push(entry);
    });
    resolve(arp_array);
  });
};

arp_table()
.then(r => console.log(x))

I have looked at other patterns for loops on SO, but, in this case, arp.table() is essentially a 'black box' and I am not sure how best to promisify its output

Ad

Answer

This particular library calls your callback with entry set to null for the second parameter when it has finished looping, so you can create a Promise like this:

const p = new Promise((resolve, reject) => {
    const arp_array = [];
    arp.table(function(err, entry) {
      if (err) 
        reject(err);
      if (entry)
        arp_array.push(entry)
      else
        resolve(arp_array);
    });
});
Ad
source: stackoverflow.com
Ad