0

JavaScript is multi-paradigm and provides (at least) 3 different error-handling strategies for synchronous code.

I have seen this question asked in the context of async functions, for which promises are clearly recommended, but what about synchronous functions?

One example would be parsing. Suppose I have a function for parsing strings into integers. This function will fail in the case of a malformed input, but how should I model this?

1. Try-catch Style

const f = () => {
  throw new Error('Something has gone wrong. ');
};

// Usage
try {
  console.log(f()); 
} catch (error) {
  console.error(error); 
}

2. Callback Style

const f = (callback) => {
  callback(new Error('Something has gone wrong. '), null);
};

// Usage
f((error, result) => {
  if (error) {
    console.error(error);
  } else {
    console.log(result);
  }
});

3. FP Style (also seen in Go)

const f = () => {
  return {
    error: new Error('Something has gone wrong. '), 
    result: null
  };
};

// Usage
const { error, result } = f();

if (error) {
  console.error(error); 
} else {
  console.log(result);
}
sdgfsdh
  • 33,689
  • 26
  • 132
  • 245
  • Depends on your design pattern I suppose. This seems like an opinion based question. I personally design my handling of synchronous code using the 2nd method if that helps but that does not mean there's anything wrong with any other method. – Adrian Feb 20 '18 at 16:06
  • Opinion based but I'd prefer promise over callback so 2 is out. Try catch I only use when calling code that can throw (so not my own) And 3 looks a bit like [railway orientated programming](https://fsharpforfunandprofit.com/rop/) which is also kind of what promises do for you, you can skip a bunch of stacked `.then` and `.catch` something in the end if anything went wrong. So my vote goes to 3. See [here](https://stackoverflow.com/a/47678417/1641941) for promises that don't fail if you need to do a `Promise.all` but rather not go the `.catch` route when one or more items fail. – HMR Feb 20 '18 at 16:15
  • @HMR Are promises really appropriate fron non-async code though? – sdgfsdh Feb 20 '18 at 16:17
  • @Adriani6 This is a broad question, I suppose, but the design implications of each approach (i.e. what they make easy and what they make hard) are sufficiently diverse and objective. – sdgfsdh Feb 20 '18 at 16:44
  • Probably nr 3 is good for synchronous railway orientated programming. – HMR Feb 20 '18 at 21:39

1 Answers1

1

Avoid (rolling your own) callback style, it makes it unnecessary complicated (and you still need the if).

Synchronous exceptions are the go-to solution. They are common, easy to understand, and have simple syntax.

If you like functional programming, you can also use an appropriate data structure to represent the possible error in your type signature. However, you would not just return an object literal, you would use a library that implements the Either datatype with all appropriate methods. There are quite a few

Bergi
  • 630,263
  • 148
  • 957
  • 1,375