---
title: 函数式进阶-管道
date: 2023-01-19 22:09:39
tags: 
  - JavaScript
  - 函数
categories: 
  - JavaScript
---

管道处理是一种比较常见的api设计方式，意思是上一步的执行结果作为下一步的入参
顺序执行

<!-- more -->

如果我们需要在JS中实现这一点
当然可以这样做
```typescript
func1(func2(func3(arg)))
```
首先这样代码很难看，其次是这样嵌套的代码调用是固定的，没有做到动态的函数式编程

### 基本形式

如果要实现一个管道，可以这样做
```javascript
// pipe函数的参数接受若干个参数, 都是Function类型
const pipe = (...funcs) => {
  // 这个pipe函数是会返回一个函数
  return inputValue => { // 这个函数的初始入参作为第一个函数的调用入参, 之后将该函数返回值作为下一个函数的入参
    return funcs.reduce((currentValue, currentFunction) => {
      return currentFunction(currentValue)
    }, inputValue)
  }
}
```
上面是使用`reduce`作用是正序执行，如果要逆序执行可以使用`reduceRight`
调用示例
```javascript
const func1 = value => {
  return value * 10
}
const func2 = value => {
  return value + 5
}
const func3 = value => {
  return value * 0.5
}
const result = pipe(func1, func2, func3)(30)
console.log(result)
```

### 异步函数
如果输入的函数是异步的，或者同步异步都有呢
那么函数的返回结果就不能立刻拿到了

```javascript
const pipeAsync = (...funcs) => {
  return async (inputValue) => {
    return funcs.reduce((chain, func) => {
      return chain.then(func)
    }, Promise.resolve(inputValue))
  }
}
```
区别就是不管函数是不是异步的，都当做异步处理，作为then的回调函数
调用示例
```javascript
const func4 = async value => {
  return value * 10
}

const func5 = value => {
  return value + 5
}

const func6 = async value => {
  return value * 0.5
}

pipeAsync(func4, func5, func6)(30).then(result2 => {
  console.log(result2)
})
```