Error Handling in `read` and `write`

In previous parts[1][2] the concept of functional asynchronous read and write was introduced, but without error handling. try/catch error handling in node.js is problematic due to asynchronous nature of operations[3]. In node.js the result of the asynchronous operation is either the error or value, returned in first or second argument of the callback function. When error occurs, the function should not continue the operations, instead it should just invoke the callback with error argument.

var read = filepath =>  
  callback => {
    let impl = filepath => {
      let options = { encoding : 'utf8' };
      fs.readFile(filepath, options, callback);
    return ('function' === typeof filepath)
      ? filepath((err, filepath) =>
        err != null ? callback(err) : impl(filepath))
      : impl(filepath);

var write = (filepath, data) =>
  callback => {
    let impl1 = (filepath, data) =>
      fs.writeFile(filepath, data, callback);
    let impl2 = filepath =>
      ('function' === typeof data)
        ? data((err, data) =>
          err != null ? callback(err) : impl1(filepath, data))
        : impl1(filepath, data);
    return ('function' === typeof filepath)
      ? filepath((err, filepath) =>
        err != null ? callback(err) : impl2(filepath))
      : impl2(filepath);

Writing to the wrong path or reading from the file that does not exist results in callback invoked with error:

write('out', read('in'))((err, result) => console.log(err, result));
{ Error: ENOENT: no such file or directory, open 'in'
    at Error (native) errno: -2, code: 'ENOENT', syscall: 'open', path: 'in' } undefined

Notice that write is not creating the file in this example because the computation completes early due to the missing file 'in'.

This pattern can be applied to any asynchronous function with fixed number of parameters that completes by calling callback with error and value.

  1. Functional Asynchronous Programming in node.js, ↩︎

  2. Better 'read' and 'write', ↩︎

  3. Error Handling in Node.js, ↩︎