Skip to content

Instantly share code, notes, and snippets.

@georgebearden
Last active August 30, 2015 23:55
Show Gist options
  • Select an option

  • Save georgebearden/ef3d6f2c60dbc80189c4 to your computer and use it in GitHub Desktop.

Select an option

Save georgebearden/ef3d6f2c60dbc80189c4 to your computer and use it in GitHub Desktop.

Coming from a background that was not heavy on callbacks, whenever I wanted to short-circuit a method I would simply "return".
For example:

public void Log(string data) 
{
  if (data == null)
    return;
    
  ...
}

Now, when writing async NodeJS applications, I have a similar tendency to treat the callback as the return, e.g.,

function log(data, callback) {
  if (!data) {
    callback('error');
  }
  
  ...
};

However, this is incorrect and quickly leads to bugs throughout the code. When the log function is called with a null data arguement, it will indeed call the error callback, but then will continue execution of the function. What is needed is a return statement after the callback, e.g.,

function log(data, callback) {
  if (!data) {
    callback('error');
    return;
  }
  
  ...
};

This will ensure the correct behavior when running the log function. Another approach the NodeJS devs use it to return the callback, e.g.,

function log(data, callback) {
  if (!data) {
    return callback('error');
  }
  
  ...
};

This approach is nice because it is very explicit. It is more explicit, which can help in the future where some developer might want to add logic in between the error callback being called and the return statement. It is also nice because it reduces the lines of code from 2 to 1. However, there have been performance tests that show it may be slightly less effecient to return a callback versus calling a callback and then returning (http://jsperf.com/return-vs-no-return/4)

An example of a bad guard function in node:

function log(data, callback) {
  if (!data) {
    callback('error');
  }
  
  callback(null);
};

Some examples of good guard functions in node:

function log(data, callback) {
  if (!data) {
    callback('error');
  } else {
    callback(null);
  }
};

function log(data, callback) {
  if (!data) {
    callback('error');
    return;
  } 
    
  callback(null);
};

function log(data, callback) {
  if (!data) {
    return callback('error');
  } 
    
  callback(null);
};

For me, the reason to use a return guard in a method vs. using an else statement is that it helps avoid nesting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment