Wrapping node.js Callback Functions

Let's define the function fn that wraps any given node.js async callback function, which makes possible to call this function in the functional way:

const fn = f => (...args) => {
  return callback => {
    const fargs = args.map(_ => ({ value : undefined, set : false }));
    const set = (n, value) => fargs[n] = { value : value, set : true };
    const done = () => {
      if (fargs.every(item => item.set))
        f.apply(null, fargs.map(item => item.value).concat([callback]));
    };
    args.forEach((arg, i) => {
      if (isFn(arg)) {
        arg((err, val) => {
          if (err != null) {
            callback(err);
            return;
          }
          set(i, val);
          done();
        });
      } else {
        set(i, arg);
      }
    });
    done();
  }
};

And now let's try it with some of the fs functions:

var realpath = fn(fs.realpath);
var readdir = fn(fs.readdir);
readdir(realpath('.', 'utf8'))((err, result) => console.log(err, result));