你应该在什么情况下会想到使用管道模式(pipe)?

本文会介绍Pipe在函数式编程中的基本概念,怎么用Pipe让我们的代码变得更美好,以及新的pipe操作符,Fancy的东西在后面!

前不久我再对axios封装的时候,并利用了观察模式进行拦截器的应用。实现了类似webpack插件的扩展修改我们的axios。最近做response的处理的时候,我发现把代码都对接到then里面处理也不是好的处理方式。

 private httpClient(mode: Method, uri: string, body: any, options?: AxiosRequestConfig) {

        const requestBody = ['GET', 'DELETE'].indexOf(mode) === 0 ?
            {
                params: body
            }
            :
            {
                data: body
            }

        return this.okHttp.getHttpClient().request({
            ...requestBody,
            url: uri,
            method: mode,
        }).then(res => {
            return res.data
        })
    }
复制代码

这个时候我需要一种模式去解耦这种关系,如果还用观察者模式就过于复杂。使用rxjs的流式操作也不是不行,但是rxjs更偏向异步操作的顺序性。而我只是想流失koa这种洋葱(pipe)示例的操作。

如果你想流去做一件事情那么pipe是一个不错的选择,可以把你的handle操作顺序放在其他地方动态的加载到then里面操作。

什么是Pipe?

先用一个最简单的例子来看一下什么是pipe,现在我们有两个最简单的函数addOneaddTwo,分别对于参数加一和加二:

const addOne = x => x + 1
const addTwo = x => x + 2
复制代码

现在我们想让一个参数通过第一个函数之后再通过第二个函数,最直接最简单的方法是:

addTwo(addOne(1)) // 4
复制代码

我们来写一个简单的pipe函数,它返回一个新的函数,来达到我们上面的目的:

const pipe = (func1, func2) => x => func2(func1(x))

const addThree = pipe(
  addOne,
  addTwo
)

addThree(1) // 4
复制代码

嗯,现在还看不出来什么好处,但是当我们要经过的Transform越来越多的时候,这样的好处就会越来越明显:

const addTen = pipe(
  addOne,
  addTwo,
  addThree,
  addFour
)
复制代码

所以我们需要一个更牛逼的pipe函数,它可以接受任意数量的参数,并从第一个开始,依次接受原始数值,输出值传递给下一个函数。等等,我们好像想到了什么,遍历一个数组,把输出值当作下一个的输入,怎么听着都和reduce很像。所以,直接用Array.prototype.reduce就可以写一个简单的pipe函数:

const pipe = ...args => x => 
  args.reduce(
    (outputValue, currentFunction) => currentFunction(outputValue),
    x
  )
复制代码

当然在es6以上的写法可以简单符号完成。

a |> b // b(a)
复制代码

代码改造

 private httpClient(mode: Method, uri: string, body: any, options?: AxiosRequestConfig) {

        const requestBody = ['GET', 'DELETE'].indexOf(mode) === 0 ?
            {
                params: body
            }
            :
            {
                data: body
            }

        return this.okHttp.getHttpClient().request({
            ...requestBody,
            url: uri,
            method: mode,
        }).then(res => {
            const response = ResponseHandle.getInstance().pipe(
                AccessTokenHandle
            )
            response(res);
            return res.data
        })
    }
复制代码

可以看到我们使用以下代码来做以后我们的业务拓展,这里这是一个小例子自己举一反三。如果你是要进一步优化会如何操作,如果是我的话。pipe需要参数做成一个数组,这个数组可以做成配置项目,需要做那些校验和流的处理我们就要那个,在配置项目里面管理函数组合。

  const response = ResponseHandle.getInstance().pipe(
        AccessTokenHandle
  )
  response(res);
复制代码

以后我们需要条件新的功能的时候,无需去看之前的屎山业务代码。添加一个就去配置一个,注意这里的pipe是简单写法,如果你的业务有顺序性的话。应当注顺序组合。如果使用rxjs的话可以创建多个观察主题自己进行组合。

export function AccessTokenHandle(res: any) {
    const { code } = res.data;
    if (code === 1000) {
        alert('数据不错喔!')
    }
}
复制代码

image.png

今天的项目的构建思维,就分享这么多。至于你们要怎么运用,要自己想想什么场景可以使用这种设计做处理。不是为了运用而运用!

おすすめ

転載: juejin.im/post/7062238031398305828