了解generator这篇文章就够了

2022/8/31 23:26:16

本文主要是介绍了解generator这篇文章就够了,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

了解generator这篇文章就够了

Generator介绍

  • generator函数是es6提出的一种异步编程的方案,可以用来替代promise来获取异步执行的结果

Generator语法

  1. Generator函数两个特征
    1. 普通函数加星号*的模式,至于星号的位置没有什么规定的要求
          // 普通函数
          function fn(){}
          // generator函数
          function * fn(){}
          function* fn(){} // 推荐
          function *fn(){}
          function*fn(){}
      
    2. 函数内部使用yield关键字,yield代表产出的意思
      • 注意:普通函数里面无法直接使用yield,否则会出现报错
          // 普通函数内部无法使用yield
          function fn(){
              yield 1;
              yield 2;
              yield 3;
          }
          fn() // 调用的时候会报错 Uncaught SyntaxError: Unexpected number
          // 带*号的函数内部可以使用yield
          function* fn(){
              yield 1;
              yield 2;
              yield 3;
          }
          fn() // 不会报错
      
  2. Generator函数的返回值
    • 普通函数的返回值看函数内部有没有写return,return后面的数据就是函数的返回值
          // 没有return
          function fn(){}
          console.log(fn()) // undefined
      
          // 有return
          function fn(){
              return 1
          }
          console.log(fn()) // 1
      
    • generator函数即使没有写return返回的也是一个遍历器对象,什么是遍历器对象呢,我们暂时可以理解这是一个带有特殊方法的对象
          // 没有return
          function* fn(){}
          console.log(fn()) // 返回一个遍历器对象
      
          // 有return
          function* fn(){
              return 1
          }
          console.log(fn()) // 返回也是一个遍历器对象
      
  3. next方法
    • 每一个generator函数调用完成之后都会返回一个遍历器对象,该对象可以调用next()方法
    • 每一次遍历器对象调用next()方法之后都会返回一个新对象,返回的对象里面有两个属性
      • value 代表next方法执行的结果
      • done 代表遍历器是否执行结束
        function* fn(){}
        var it = fn()
        console.log(it.next()) // {value: undefined, done: true}
    
    • 如果generator函数有写return的话,那么返回的遍历器对象调用next方法就有一个value值,就是return返回的结果,但是这个遍历器还是执行一次就结束了
        function* fn(){
            return 1
        }
        var it = fn()
        console.log(it.next()) // {value: 1, done: true}
    
    • 如何让一个遍历器多次执行呢?我们可以在generator函数里面使用刚才讲的yield表达式,这样我们就可以多次调用遍历器的next方法
      • 第一次调用next()方法,返回一个对象,该对象的value值是第一个yield表达式之后的值,返回done是false,代表遍历器没有执行结束
      • 第二次调用next()方法,返回一个对象,该对象的value值是第二个yield表达式之后的值,返回done是false,代表遍历器没有执行结束
      • 第三次调用next()方法,返回一个对象,该对象的value值是第三个yield表达式之后的值,返回done是false,代表遍历器没有执行结束
      • 第四次调用next()方法,返回一个对象,该对象的value值是undefined,返回done是true,代表遍历器执行结束
          function* fn(){
              yield 1
              yield 2
              yield 3
          }
          var it = fn() // it是返回的遍历器
          // it遍历器当使用yield之后可以多次调用
          console.log(it.next()) // {value: 1, done: false}
          console.log(it.next()) // {value: 2, done: false}
          console.log(it.next()) // {value: 3, done: false}
          console.log(it.next()) // {value: undefined, done: true}
      
  4. next()方法传参
    • yield表达式执行完成之后没有或者说每一次默认的返回值为undefined
          function* fn(){
              var x = yield 1
              console.log(x) // undefined
              var y = yield 2
              console.log(y) // undefined
              var z = yield 3
              console.log(z) // undefined
          }
          var it = fn()
          console.log(it.next())
          console.log(it.next())
          console.log(it.next())
          console.log(it.next())
      
    • 每一次调用next方法传递的参数就是上一个yield的返回值
          function* fn(){
              var x = yield 1
              console.log(x) // 10
              var y = yield 2
              console.log(y) // 20
              var z = yield 3
              console.log(z) // 30
          }
          var it = fn()
          console.log(it.next())
          console.log(it.next(10))
          console.log(it.next(20))
          console.log(it.next(30))
      
    • 注意: 第一次调用next无法传参,及时传了也没有任何作用,因为第一次next方法相当于是启动整个generator的函数,如果需要第一次调用next传参,需要在generator函数外面再包裹一层
          function parent(){
              function* gen(){
                  var x = yield 1
                  console.log(x)
                  var y = yield 2
                  console.log(y)
                  var z = yield 3
                  console.log(z)
              }
              // 相当于在parent里面完成对generator函数的第一次next调用
              var it = gen()
              it.next()
              return it
          }
          // 这样我们再次使用generator的时候 就可以传递参数了
          var it = parent()
          console.log(it.next(10))
          console.log(it.next(20))
          console.log(it.next(30))
      
  5. throw方法
    • throw方法是遍历器对象的另一种方法,作用和next相同,不同的地方就是throw是抛出异常错误,一旦异常抛出,在generator函数里面对应的yield语法执行的时候就可以捕获异常,yield下面的语句就不会往下运行了
          function* fn() {
              var x = yield 1
              console.log(x) // 10
              var y = yield 2 // 程序执行到此处会报错,就不会在往下执行了 下一个next就不会被调用
              console.log(y)
              var z = yield 3
              console.log(z)
          }
          var it = fn()
          console.log(it.next())
          console.log(it.next(10))
          console.log(it.throw(20)) // 此处抛出异常
          console.log(it.next(30))
      
  6. return方法
    • return方法也是遍历器对象的一种方法,作用和next相同,不同的地方就是return方法相当于提前结束generator函数的执行,后面再次执行遍历器next方法的结果就不是yield后面的结果,全部为undefined
          function* fn() {
              var x = yield 1
              console.log(x) // 10
              var y = yield 2 // 程序执行到此处会报错,就不会在往下执行了 下一个next就不会被调用
              console.log(y)
              var z = yield 3
              console.log(z)
          }
          var it = fn()
          console.log(it.next())     // {value: 1, done: false}
          console.log(it.return(10)) // {value: 10, done: true}
          console.log(it.next(20))   // {value: undefined, done: true}
          console.log(it.next(30))  // {value: undefined, done: true}
      

generator在异步任务中的使用

  • 没有使用generator导致的地狱回调
        ajax('./serve/a.php?num1=25', function (res) {
            ajax(`./serve/b.php?num2=${res}`, function (res2) {
                ajax(`./serve/c.php?num3=${res2}`, function (res3) {
                    console.log(res3)
                })
            })
        })
    
  • 使用generator
        var it = gen()
        it.next()
        function* gen(){
            var res1 = yield ajax('./serve/a.php?num1=25', function(res){
                it.next(res)
            })
            var res2 = yield ajax(`./serve/b.php?num2=${res1}`, function(res){
                it.next(res)
            })
            yield ajax(`./serve/c.php?num3=${res2}`, function(res){
                console.log(res)
            })
        }
    


这篇关于了解generator这篇文章就够了的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程