Alex Webster
Alex Webster

Reputation: 747

Node- Promisify a Function that Contains a Loop

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

Upvotes: 0

Views: 444

Answers (2)

charlietfl
charlietfl

Reputation: 171690

Looking at the source code , the callback gets called in a loop but also gets called after loop ends with entry as null

So you can use a conditional to resolve the promise:

const arp_table = function() {
  var arp_array = [];
  return new Promise((resolve, reject) => {
    arp.table((err, entry) => {
      if(err){
        reject(err);
      }
      if (entry) {
        arp_array.push(entry);
      } else {
        resolve(arp_array);
      }
    });

  });
};

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

Upvotes: 1

laptou
laptou

Reputation: 7039

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

Upvotes: 1

Related Questions