【前端进阶】解决maybe函子问题的神奇函子 --- Either函子

1,096 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文同时参与 「掘力星计划」          ,赢取创作大礼包,挑战创作激励金

前言

书接上文,我们要进行上文的maybe函子的优化啦! 上一章传送门:juejin.cn/post/701840…

什么是Either函子

  • Either两者中的任何一个,类似于if...else...的处理
  • 异常会让函数变得不纯,Either函子可以用来做异常处理

开始处理

1. 需求确定

磨刀不误砍柴工,我们要先明确一下需求 解决maybe函子不能确定null出现位置的函子。不仅处理什么地方出现的null,也可以用来获取异常出现的位置和异常的信息。 ok,是时候开始实现Either函子了,因为他是二选一,所以我们要创建两个类型leftright

```js
class left {
    ...
}
class right {
    ...
}
```

2. 类编写

在这两个类中,我们对其进行方法体的编写,它们都需要一个静态方法、一个map方法,就是简单的函子,可以回顾:简单函子编写

```js
class Left {
  static of (value) {
    return new Left(value)
  }
  constructor (value) {
    this._value = value
  }
  map (fn) {
    return this
  }
}
class Right {
   static of (value) {
    return new Right(value)
  }
  constructor (value) {
    this._value = value
  }
  map (fn) {
    return Right.of(fn(this._value))
  }
}
```
到这,这两个类我们已经编写完毕了,其实我们观察一下其实都是差不多的,我们其实可以进行一下修改,不过,现在就不进行修改,这样方便大家理解

3. 函子的区别

我们用上面实现的两个类实现两个函子,我们来观察一下他们有什么区别

```js
let r1 = Right.of(12).map(x => x + 2)
let r2 = Left.of(12).map(x => x + 2)
console.log(r1)
console.log(r2)
```

image.png 我们可以看到Right中的值是 12+2 = 14正确的输出的,但是Left却是返回了原来的参数,主要是因为Left中的map是直接返回了this

Left直接返回原来的函子,用来捕捉异常,Right用来在没有异常的时候执行输入的fn并返回一个函子。

**为什么要这么做呢?**

4. 为什么需要两种函子

为了解决上面的疑问,来个例子给大家演示一下,方便加深理解

例如传入一个会报错的JSON对象和正常的JSON对象,区别如下:
```js
function parseJSON (str) {
    try {
        return Right.of(JSON.parse(str))
    } catch (e) {
        return Left.of({ error: e.message})
    }
}
// 会出现错误的情况
let r = parseJSON('{ name: zs}')
console.log(r)
let r1 = parseJSON(JSON.stringify({ name:'zs'} ))
console.log(r)
```
![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/472abe33d8004bb9998ddfd576a1fc5f~tplv-k3u1fbpfcp-watermark.image?)

5. 小结

到这,Either函子 就已经演示完毕了,我们可以通过这个函子处理异常,存储错误信息 either函子本质上就是两个函子组合的,一个函子走正确的逻辑,另外一个函子用来捕捉错误信息

完整代码

class Left {
  static of (value) {
    return new Left(value)
  }
  constructor (value) {
    this._value = value
  }
  map (fn) {
    return this
  }
}
class Right {
   static of (value) {
    return new Right(value)
  }
  constructor (value) {
    this._value = value
  }
  map (fn) {
    return Right.of(fn(this._value))
  }
}
//定义一个函数
function parseJSON (str) {
  try {
      return Right.of(JSON.parse(str))
  } catch (e) {
      //用来存储错误信息
      return Left.of({ error: e.message})
  }
}
// 传入错误的数据
let r = parseJSON('{ name: zs}')
console.log(r)
// 传入正确的数据
let r1 = parseJSON(JSON.stringify({ name:'zs'} ))
console.log(r1)
let r3 = Right.of(12).map(x => x + 2)
console.log(r3)
let r4 = Left.of(12).map(x => x + 2)
console.log(r4)

总结

本篇我们学会了Either函子并且了解了他的构成,在之后我们准备深入函子学习,进入IO函子篇,下一章再见!

来到这里的看官老爷给个赞吧!

下期见.webp