[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 ...
随机推荐
- python中if和elif的区别
多个if语句是每次单独判断 比如: 例子一: a = 5 if a < 6: #条件1 print(1) if a < 7: #条件2 print(2) else: print(3) 条件 ...
- Linux下Makefile学习笔记
makefile 可以用于编译和执行多个C/C++源文件和头文件. (1) #include "file.h" 和 #include <file.h> 的区别 #inc ...
- [转]iOS开发new与alloc/init的区别
1.在实际开发中很少会用到new,一般创建对象咱们看到的全是[[className alloc] init] 但是并不意味着你不会接触到new,在一些代码中还是会看到[className new], ...
- ElasticSearch6 报错FORBIDDEN/12/index read-only / allow delete (api)
FORBIDDEN/12/index read-only / allow delete (api) 官方解决方法: curl -XPUT -H "Content-Type: applicat ...
- Scrapy学习篇(三)之创建项目
创建项目 创建项目是爬取内容的第一步,之前已经讲过,Scrapy通过scrapy startproject <project_name>命令来在当前目录下创建一个新的项目. 下面我们创建一 ...
- Linux中的mysql操作(2)
1.终端启动MySQL:/etc/init.d/mysql start: 2.登录MySQL:mysql –u root -p (用root账户登录),然后输入密码: 3.查看所有的数据库名字:sho ...
- [BZOJ4825][HNOI2017]单旋(线段树+Splay)
4825: [Hnoi2017]单旋 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 667 Solved: 342[Submit][Status][ ...
- [BZOJ4555][TJOI2016&HEOI2016]求和(分治FFT)
4555: [Tjoi2016&Heoi2016]求和 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 525 Solved: 418[Sub ...
- SpringBoot 部署 docker 打包镜像
SpringBoot 部署 docker 打包镜像 环境: 1.代码编写工具:IDEA 2.打包:maven 3.docker 4.linux 7.JDK1.8 8.Xshell 9.Xftp 第一步 ...
- Springboot项目与vue项目整合打包
我的环境 * JDK 1.8 * maven 3.6.0 * node环境 1.为什么需要前后端项目开发时分离,部署时合并? 在一些公司,部署实施人员的技术无法和互联网公司的运维团队相比,由于各种不定 ...