0

I am writing a ping application that logs every ping to a log file. Depending on the result I write an info or a error entry.

Here is the ping function:

function pingServer(item){
    var monitor = new Monitor({
        website: item.url,
        interval: interval
    });
    monitor.on('up', writeInfo);
    monitor.on('down', writeError);
}

I would like to have a unique callback function writeLog instead of writeInfo and writeError functions, but I dont know how to pass an argument in that callback.

So instead of

function writeInfo(res){
    logger.info(getVarLine(res));
}


function writeError(res){
    logger.error(getVarLine(res));
}

I would have something like:

function writeLog(res, level){
    if (level=='info'){
        logger.info(getVarLine(res));
    } else {
        logger.error(getVarLine(res));
    }
}
E Rodriguez
  • 323
  • 1
  • 2
  • 14

2 Answers2

3

Here are three options:

  1. Use .bind() to automatically prepend arguments to the callback (technically this creates a new function stub that adds that argument).
  2. Manually create your own wrapper function that adds the argument.
  3. Create a new version of .on() that accepts your level argument and adds it to the callback before calling the callback.

Using .bind()

If you are not relying on a value of this being passed into your callback, then you can use .bind() to create a new function that will have the level argument automatically prepended to the callback arguments.

// note how the arguments had to be switched here so level was first to match
// up with how .bind() works
function writeLog(level, res){
    if (level=='info'){
        logger.info(getVarLine(res));
    } else {
        logger.error(getVarLine(res));
    }
}

function pingServer(item){
    var monitor = new Monitor({
        website: item.url,
        interval: interval
    });
    monitor.on('up', writeLog.bind(null, level));
    monitor.on('down', writeLog.bind(null, level));
}

Manually Creating Your Own Wrapper Function

Or, you can create your own wrapper function that returns a function, but captures the parameter you wanted:

function writeLogCallback(level) {
    return function(res) {
        if (level=='info'){
            logger.info(getVarLine(res));
        } else {
            logger.error(getVarLine(res));
        }
    }
}

function pingServer(item){
    var monitor = new Monitor({
        website: item.url,
        interval: interval
    });
    monitor.on('up', writeLogCallback(level));
    monitor.on('down', writeLogCallback(level));
}

Creating a Replacement for .on()

Or, you can create a wrapper for monitor.on() that captures your level value:

Monitor.prototype.onWithLevel = function(event, level, callback) {
    this.on(event, function(res) {
        return callback(res, level);
    });
}

function writeLog(res, level){
    if (level=='info'){
        logger.info(getVarLine(res));
    } else {
        logger.error(getVarLine(res));
    }
}

function pingServer(item){
    var monitor = new Monitor({
        website: item.url,
        interval: interval
    });
    monitor.onWithLevel('up', level, writeLog);
    monitor.onWithLevel('down', level, writeLog);
}
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thanks! Just one question, when you say "If you are not relying on a value of `this`" what do you mean? – E Rodriguez Mar 17 '16 at 22:27
  • @ERodriguez - `.bind()` requires you to pass it, in advance, the value of `this` that will be set for the callback function. If you aren't using `this` in your handler, then that will not matter. If you are, then you will have to either make sure you pass the right value for `this` or you will have to use one of the other techniques. If you don't know what `this` is or how it's set, then see this answer: http://stackoverflow.com/questions/28016664/when-you-pass-this-as-an-argument/28016676#28016676 – jfriend00 Mar 17 '16 at 22:28
0

Here's how you could achieve what you want (ie pass an argument to a callback):

monitor.on('up', writeLog('info'));
monitor.on('down', writeLog('error'));

// You pass the log level
function writeLog(level) {
    // and you return a function that will be called
    // with your data when the event is triggered
    return function(res) {
        if (level=='info'){
            logger.info(getVarLine(res));
        } else {
            logger.error(getVarLine(res));
        }
    }
}
cl3m
  • 2,791
  • 19
  • 21