zoukankan      html  css  js  c++  java
  • 学习笔记:javascript中的Generator函数

    最近在学习redux-saga,由于redux-saga需要使用Generator函数,所以下来就回顾了一下Generator

    Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同

    写法上Generator函数与普通函数没什么区别,只是在function关键字后面多了一个*号,函数内部多了一个yield关键字

    function* demo() {
      console.log(1)
      yield 111
      console.log(2)
      yield 222
      console.log(3)
      return 333
    }
    

    上面的函数即为一个Generator函数,Generator调用后并不会直接执行,而是返回一个指向内部状态的指针对象需要调用该指针对象的next方法才会向下执行,当遇到yield关键字的时候,函数会挂起,交给外部,直到遇到下一次调用next方法

    let g = demo()

    此时若我们第一次调用

    let val1 = g.next()
    
    // 打印 1,val1 = {value: 111, done: false}
    
    let val2 = g.next()
    // 打印 2,val2 = {value: 222, done: false}
    
    let val3 = g.next()
    // 打印 3,val3 = {value: 333, done: true}
    

    根据结果我们可以很清楚的看到当返回值的donetrue的时候就代表Generator执行完毕,此外Generator函数还可以被循环

    
    for (let val of demo()) {
      console.log(val)
    }
    // val依次会打印出 111、222,注意当done为true的时候不会打印value的值
    

    当然Generator在工作中最常用到的就是处理异步函数,下面举个例子:

    
    function demo(a, b) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(a + b)
        }, 1000)
      })
    }
    
    
    function* gen(val) {
      let a = yield demo(1, 2)
      console.log(a)
      let b = yield '123'
      return b
    }
    
    

    这里需要注意的是,变量a的值是需要next方法传入的

    let g = gen()
    let {value} = g.next()
    

    此时函数中的变量a的值就是再次调用next传入的值, 比如g.next(value),则此时a的值就是一个Promise的实例,显然这不是我们想要的,我们期望拿到的是Promise.resolve的值

    那么根据上面的结果我们可以编写一个Generator执行器

    function execGen(gen) {
      let g = gen()
    
      function deep(val) {
        let {value, done} = g.next(val)
        if (done) {
          return
        }
        if (value instanceof Promise) {
          value.then(data => {
            deep(data)
          })
        } else {
          deep(value)
        }
      }
      deep()
    }
    
    execGen(gen)
    
    // gen函数的console会正确的打印出值3
    
    

    其实如果不是redux-saga的话我感觉我工作中基本不会用到Generator函数,个人感觉更优雅的是async/await 来处理异步情况

    async function handler() {
      try{
        let val = await demo()
      }catch (e) {
        
      }
    }
    

    最后还是期望有大佬能够帮忙指出相比于async/await,Generator有什么优势_

  • 相关阅读:
    Git本地仓库push至GitHub远程仓库每次输入账户密码问题解决(亲测可行)
    Laravel5.5+ 区分前后端用户登录
    word 中Sentences、Paragraph等含义和用法
    Word转图片word
    Word文档编号工具,Word标题,图、表手动编号工具
    Word电子扫描器 Word文档转换为图片Pdf,Word文档扫描成Pdf工具
    如何用vba给一个word表格的最后插入一行
    PPT电子扫描仪 ppt转换为图片Pdf工具
    Word文档只读加密工具
    在c#应用程序中使用IrisSkin2.dll美化界面
  • 原文地址:https://www.cnblogs.com/songbw/p/11065561.html
Copyright © 2011-2022 走看看