[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 ;
- }
- }
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: })
- } 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 => ,
- 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 => ,
- 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 => ,
- x => x.port);
---------
- // SETUP: fake fs
- //==========
- const fs = {
- readFileSync: name => {
- if(name === 'config.json') {
- return JSON.stringify({port: })
- } 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 => ,
- x => x.port);
- console.log(getPort('config.json'))
-----
You can also rename 'flatMap' to 'chain'. Sometime 'flatMap' or 'chain' looks similar to 'fold' implementation. But the meaning is different, here 'chain / flatMap' says It says, "If we're going to return another Either
, we are going to use chain
instead of map." 'fold' says just get the value out of the box, it's done!
[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 func ...
- JS function document.onclick(){}报错Syntax error on token "function", delete this token - CSDN博客
原文:JS function document.onclick(){}报错Syntax error on token "function", delete this token - ...
- 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 ...
- Erlang error handling
Erlang error handling Contents Preface try-catch Process link Erlang-way error handling OTP supervis ...
- MySQL Error Handling in Stored Procedures 2
Summary: this tutorial shows you how to use MySQL handler to handle exceptions or errors encountered ...
- setjmp()、longjmp() Linux Exception Handling/Error Handling、no-local goto
目录 . 应用场景 . Use Case Code Analysis . 和setjmp.longjmp有关的glibc and eglibc 2.5, 2.7, 2.13 - Buffer Over ...
- Error Handling
Use Exceptions Rather Than Return Codes Back in the distant past there were many languages that didn ...
- Error Handling and Exception
The default error handling in PHP is very simple.An error message with filename, line number and a m ...
- Clean Code–Chapter 7 Error Handling
Error handling is important, but if it obscures logic, it's wrong. Use Exceptions Rather Than Return ...
随机推荐
- FastReport.Net使用:[9]多栏报表(多列报表)
方法一:使用页的列属性(Page Columns) 1.绘制报表标题 2.设置页的列数量为3,其他默认不变.报表设计界面便如下呈现. 3.报表拷贝前面[分组]报表的内容. 4.就这么简单,一张多栏报表 ...
- [CODE FESTIVAL 2018]Sushi Restaurant
题意:有$n$个人,对每个人,他有$p_i$的概率饥饿值为$x_i$($1\leq i\leq m$),你现在要做$n$盘寿司,每盘寿司有一定的数量,当这$n$个人的饥饿值确定后他们会自己选择最优的( ...
- easyui 属性集合
easyUI属性汇总 属性分为CSS片段和JS片段. CSS类定义:1.div easyui-window 生成一个window窗口样式. 属性如下: 1)modal:是否生成模态窗口.true[是] ...
- CDOJ 1048 Bob's vector 三分
Bob's vector 题目连接: http://acm.uestc.edu.cn/#/problem/show/1048 Description Bob has a vector with mm ...
- VK Cup 2016 - Qualification Round 1 (Russian-Speaking Only, for VK Cup teams) C. Promocodes with Mistakes 水题
C. Promocodes with Mistakes 题目连接: http://www.codeforces.com/contest/637/problem/C Description During ...
- php 安装 Redis 扩展
开发环境安装包为:wamp3.1.0,安装成功后 wamp/bin 目录下有php以下几个版本: 这里以php7.1.9为例进行redis扩展安装,其他php版本也是一样的. 进行安装 step 1: ...
- linux基础命令学习(二)文件和目录操作
1.变换当前目录(change directory) cd /home 进入 '/ home' 目录' (change directory) cd .. 返回上一级目录 cd .. ...
- 将多层级xml解析为Map
/** * 解析xml的工具类 * 1.将多层级xml解析为Map */ public class ParseXmlUtil { public static final String TAG = &q ...
- Use an LM317 as 0 to 3V adjustable regulator
Most engineers know that they can use an inexpensive, three-terminal adjustable regulator, such as F ...
- JavaScript如何获取/计算页面元素的offset?
问题 通过点击一控件,在控件的下面显示一个浮动层,通常的做法是:获取此控件的offset值,再计算出浮动层的top,left等css属性的值,赋值即可. 那么下面就看一下如何获取控件的offset值 ...