DEV Community


Discussion on: Compact or Verbose Codestyle?

qm3ster profile image
Mihail Malo

I don't think "Idiomatic JavaScript" is something to be particularly proud of, good patterns aren't the most popular here.

The approach with .error seems more conventional though, since this is similar to what you'd get in a JSON response on a remote error. (I only noticed the second example is literally await fetch after I finished writing this. haha)

Promises are already essentially Future<Result<T,E>>, with await really meaning (await promise).unwrap(), which IMHO is a big design flaw. This means that there isn't a built in Result type which we could use rich combinators with, while we can't properly express infalible futures like timeouts, which will never reject. And once await is added to the mix, we end up having to do the traditional, "idiomatic" try-catch around it.

What if you have a function that can throw, and on success returns a promise that might reject? Today you have to do:

try {
  const promise = beginThang()
} catch (err) {
  // handle E1
let /* wow, so glad this will be a mutable binding now */ result
try {
  result = await promise
} catch (err) {
  // handle E2
return makeUseOf(result)

While it could have been:

  .mapErr(err => {/*  handle E1  */}) // line optional, can just bubble error
  .andThen(async res => {
    (await res)
      .mapErr(err => {/*  handle E2  */}) // line optional, can just bubble error

Note how we get a Result<Future<Result<T,E2>>,E1> from beginThang and ourselves return a Result<Future<Result<T2,E4>>,E3> (or Result<Future<Result<T2,E2>>,E1> if we just bubble errors), so immediate errors can be handles synchronously instead of wrapping our bad outcomes in a Promise.reject(err) so they wait until the next round of the event loop.

Thread Thread
qm3ster profile image
Mihail Malo

Another thing that is not used at all in "idiomatic JavaScript" is dependency injection.