一、什么是generator函数
    (1)generator本身是用来生成迭代器的。在async和await被官方正式引入标准前用来模拟async和await,作为一另种js异步编程解决方案。
    generator函数执行过程中可以暂停(使用yield)再继续(调用遍历器对象next方法)暂停的时候将函数执行权交出给其他函数,比如异步操作,等其他函数执行完了以后,执行权会返回回来,此时可以拿到异步操作的结果,继续恢复执行。

    1. //* 可以挨着function或者函数名,但是中间必须有空格
    2. function* myGenerator(){
    3. yield setTimeout(()=>{
    4. console.log('其他函数执行')
    5. },1000);
    6. yield new Promise((resolve)=>{
    7. setTimeout(()=>{resolve('resolved')},1000)
    8. })
    9. return 'value returned'
    10. }
    11. let myIterator = myGenerator()
    12. myIterator.next() //{value: 定时器id, done:false}
    13. myIterator.next() //{value: promise, done:false}
    14. myIterator.next() //{value: 'value returned', done:true}
    1. 2yieldreturn对比<br />yield可以暂停函数执行,并将后面表达式的值(**惰性求值**,遇到next方法后才会求值)作为返回对象的value值,可暂停多次<br />return可以返回值,直接终止函数执行<br />(3next方法<br />next方法的作用是,**推动函数执行**,如果遇到yield,函数交出执行权,<br />next参数为**上一次yield表达式的值**。第一次调用next方法时传的参数是在generator函数中接受不了的,因为第一次调用next方法,遇到yield,函数就暂停运行,yield表达式并没有进行求值计算。
    1. function *gen(){
    2. let a = yield 123 + 567;
    3. console.log(a, 'a')
    4. let b = yield 123 + 678;
    5. console.log(b,'b')
    6. }
    7. let iter = gen();
    8. iter.next() // 函数开始执行,遇到yield暂停
    9. iter.next(2) // =>2 'a' 上一次yield方法表达式为
    10. iter.next(3) // =>3 'b'
    11. // 如果没有传参,yield表达式的值为undefined

    二、迭代器和遍历
    如果用遍历来执行一些函数,遍历不会中断,只能在每次迭代中增加逻辑,迭代器可以精确控制每一次迭代,可以避免无意义的迭代。
    使用场景:中间件的迭代调用,中间件一般会有next方法,只有调用next方法后,才会执行下一个中间件。
    路由钩子router.beforeEach,axios拦截器中都有next方法,调用next方法才会进入下一步。
    遍历和迭代好比上楼梯,遍历是走过每一层楼,整个过程是连续的,迭代是中间的一个动作,迭代一次,上一层楼。

    三、手写generator函数
    核心是函数返回一个对象,每次调用迭代器对象的next方法,迭代数组一次

    1. function generator (arr){
    2. let arrLenght = arr.length,
    3. currentIndex = 0;
    4. return {
    5. next(){
    6. return {value: arr[currentIndex++], done: currentIndex >= arrLenght}
    7. }
    8. }
    9. }
    10. let iterator = generator([1,2,3,4,5]);
    11. console.log(iterator)

    四、generator与iterator在一系列中间件执行中的引用。
    核心思想就是:将函数数组传入生成器生成迭代器,然后先调用init函数,进行第一次迭代,给函数传入next方法(调用迭代器next方法,将迭代结果传入是否迭代判断函数进行递归操作),调用数组里的函数。

    1. ;(function(functions){
    2. function *functGenerator(){
    3. for(let item of functions){
    4. //之前把item执行了,导致后面报错
    5. yield item
    6. }
    7. }
    8. let iterator = functGenerator();
    9. //这个函数是用来接收每次迭代返回的对象,根据done来判断是否进行迭代,并提供下一次迭代功能
    10. function checkNextDo(iteratorResult){
    11. //数组迭代最后到最有一个元素时,done还是为false,之后迭代返回对象的done才为true,
    12. //所以这里先调用函数还是先判断是否迭代结束都不影响
    13. if(iteratorResult.done){
    14. return
    15. }else{
    16. //没有迭代完成,接续迭代,此时需要传一个参数函数,提供下一次迭代功能,然后再判断
    17. //调用当前迭代到的函数
    18. iteratorResult.value(function(){
    19. checkNextDo(iterator.next())
    20. })
    21. }
    22. }
    23. function init(){
    24. checkNextDo(iterator.next())
    25. }
    26. init()
    27. })(
    28. [
    29. function test1(next){
    30. console.log('test1')
    31. next()
    32. },
    33. function test2(next){
    34. console.log('test3')
    35. next()
    36. },
    37. function test3(next){
    38. console.log('test3')
    39. next()
    40. },
    41. function test4(next){
    42. console.log('test4')
    43. },
    44. ])
    45. // test1
    46. // test2
    47. // test3