# 前置知识点(二)

# 问题--关于next函数

如下所示,我们先声明一个arr,并在这个数组里push两个函数,每个函数可以传一个参数next

let arr = [];

/** next参数,是一个函数类型 */
arr.push((next) => {
  console.log(1);
  next();
  console.log(3);
});
arr.push((next) => {
  console.log(2);
  next();
  console.log(4);
});

1
2
3
4
5
6
7
8
9
10
11
12
13
14

最终,我希望实现的效果就如同koa一样,打印顺序是1,2,4,3,那么next()到底有什么魔力呢,一起来看看吧

# 思路分析

  • 其实只要当next()执行的时候,把后面函数插入进来就可以实现上面的打印效果,即如下伪代码
(next) => {
  console.log(1);
// next(); 替换成后面的4-8行的内容
    ((next) => {
    console.log(2);
    // next(); 
    console.log(4);
    }()
  console.log(3);
}
1
2
3
4
5
6
7
8
9
10
  • 这些函数都是在数组里,那我能不能想个办法,让第一个函数next时,执行下一个函数呢,答案是递归 `

# 解决方案

根据思路分析,我们知道, 接下来构造的函数要在next()时,调用arr里面的下一个函数,直到全部调用完, compose函数如下

function compose(arr) {
  return dispatch(0); //先调用arr[0],即执行第一个函数
  function dispatch(i) {
    let fn = arr[i];
    if (!fn) return; //当数组里面函数全部执行完之后,return
    try {
        // 在第一轮递归中,把arr[1]当做arr[0]执行时候的参数
        // 也就是把arr[1]当作next,传入arr[0]中
      return fn(() => dispatch(i + 1)); 
    } catch (e) {
      console.error("err");
    }
  }
}
compose(arr);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

你可以在这里查看示例 (opens new window)

compose的本质就是不断的递归调用,并且每一次调用arr[i+1]位置的函数