[JS Compose] 3. Use chain for composable error handling with nested Eithers (flatMap)

We refactor a function that uses try/catch to a single composed expression using Either. We then introduce the chain function to deal with nested Eithers resulting from two try/catch calls.

For example we have this code using try & catch:

const getPort = () => {
  try {
    const file = fs.readFileSync(‘config.json‘);
    const c = JSON.parse(file);
    return c.port;
  } catch(e) {
    return 3000;
  }
}

And now, we want to use Either to rewirte the code:

// SETUP: fake fs
//==========
const fs = {
  readFileSync: name => {
    if(name === ‘config.json‘) {
      return JSON.stringify({port: 8888})
    } else {
      throw(‘missing file!‘)
    }
  }
}

//=================

const Right = x => ({
    map: f => Right(f(x)),
    fold: (f, g) => g(x),
    toString: () => `Right(${x})`
  });

const Left = x => ({
  map: f => Left(x),
  fold: (f, g) => f(x),
  toString: () => `Left(${x})`
});

const fromNullable = x =>
  x != null ? Right(x): Left(null);

const tryCatch = f => {
  try {
    return Right(f());
  } catch(e) {
    return Left(e);
  }
}

//=========================
const getPort = () =>
  tryCatch(() => fs.readFileSync(‘config.json‘))
  .map(f => JSON.parse(f))
  .fold(
    x => 3000,
    x => x.port);

console.log(getPort(‘config.json‘))

We wrote the function ‘tryCatch‘, the idea is put the code need to be checked in try, when success call ‘Right‘, error, call ‘Left()‘.

tryCatch(() => fs.readFileSync(‘config.json‘))

Read the file, is success, will return file content. If not, then goes to set default 3000.

  .fold(
    x => 3000,
    x => x.port);

It works, but we still miss one things, in the old code, the ‘JSON.parse‘ are also wrapped into try catch.

const getPort = () =>
  tryCatch(() => fs.readFileSync(‘config.json‘)) //Right(‘{port:8888}‘)
  .map(f => tryCatach(() => JSON.parse(f))) //Right(Right({port:8888}))

But once we also wrap parseing code into tryCatch function, the return value is 2d-Right. So we want to flatten it.

const Right = x => ({
    map: f => Right(f(x)),
    flatMap: f => f(x),
    fold: (f, g) => g(x),
    toString: () => `Right(${x})`
  });

const Left = x => ({
  map: f => Left(x),
  flatMap: f => f(x),
  fold: (f, g) => f(x),
  toString: () => `Left(${x})`
});

We add ‘flatMap‘, so instead of putting the value into Right() or Left(), we just return the value. Because we know the value passed in is already a Right or Left.

const getPort = () =>
  tryCatch(() => fs.readFileSync(‘config.json‘)) //Right(‘{port:8888}‘)
  .flatMap(f => tryCatch(() => JSON.parse(f))) //Right({port:8888})
  .fold(
    x => 3000,
    x => x.port);

---------

// SETUP: fake fs
//==========
const fs = {
  readFileSync: name => {
    if(name === ‘config.json‘) {
      return JSON.stringify({port: 8888})
    } else {
      throw(‘missing file!‘)
    }
  }
}

//=================

const Right = x => ({
    map: f => Right(f(x)),
    flatMap: f => f(x),
    fold: (f, g) => g(x),
    toString: () => `Right(${x})`
  });

const Left = x => ({
  map: f => Left(x),
  flatMap: f => f(x),
  fold: (f, g) => f(x),
  toString: () => `Left(${x})`
});

const fromNullable = x =>
  x != null ? Right(x): Left(null);

const tryCatch = f => {
  try {
    return Right(f());
  } catch(e) {
    return Left(e);
  }
}

//=========================
const getPort = () =>
  tryCatch(() => fs.readFileSync(‘config.json‘)) //Right({port:8888})
  .flatMap(f => tryCatch(() => JSON.parse(f))) //Right(Right({port:8888}))
  .fold(
    x => 3000,
    x => x.port);

console.log(getPort(‘config.json‘))
时间: 2024-11-06 22:21:17

[JS Compose] 3. Use chain for composable error handling with nested Eithers (flatMap)的相关文章

JS function document.onclick(){}报错Syntax error on token "function", delete this token

JS function document.onclick(){}报错Syntax error on token "function", delete this token function document.onclick() //任意点击时关闭该控件 //ie6的情况可以由下面的切换焦点处理代替 {    with(window.event)   { if (srcElement != outObject && srcElement != outButton)    

[JS Compose] Understand 'Box' or 'Container', they are just like Array!

We'll examine how to unnest function calls, capture assignment, and create a linear data flow with a type we call Box. This is our introduction to working with the various container-style types. At first, might not be comforable with 'Box' or 'Contai

Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十二)之Error Handling with Exceptions

The ideal time to catch an error is at compile time, before you even try to run the program. However, not all errors can be detected at compile time. To create a robust system, each component must be robust. By providing a consistent error-reporting

转 InnoDB Error Handling

14.20.4 InnoDB Error Handling Error handling in InnoDB is not always the same as specified in the SQL standard. According to the standard, any error during an SQL statement should cause rollback of that statement. InnoDB sometimes rolls back only par

[RxJS] Error handling operator: catch

Most of the common RxJS operators are about transformation, combination or filtering, but this lesson is about a new category, error handling operators, and its most important operator: catch(). Basic catch( err => Observable): var foo = Rx.Observabl

Error Handling and Exception

The default error handling in PHP is very simple.An error message with filename, line number and a message describing the error is sent to the browser. PHP has different error handling methods: Simple "die()" statements Custom errors and error t

MySQL Error Handling in Stored Procedures 2

Summary: this tutorial shows you how to use MySQL handler to handle exceptions or errors encountered in stored procedures. When an error occurs inside a stored procedure, it is important to handle it appropriately, such as continuing or exiting the c

MySQL Error Handling in Stored Procedures---转载

This tutorial shows you how to use MySQL handler to handle exceptions or errors encountered in stored procedures. When an error occurs inside a stored procedure, it is important to handle it appropriately, such as continuing or exiting the current co

setjmp()、longjmp() Linux Exception Handling/Error Handling、no-local goto

目录 1. 应用场景 2. Use Case Code Analysis 3. 和setjmp.longjmp有关的glibc and eglibc 2.5, 2.7, 2.13 - Buffer Overflow Vulnerability 1. 应用场景 非局部跳转通常被用于实现将程序控制流转移到错误处理模块中:或者是通过这种非正常的函数返回机制,返回到之前调用的函数中 1. setjmp.longjmp的典型用途是异常处理机制的实现:利用longjmp恢复程序或线程的状态,甚至可以跳过栈中