学习笔记:javascript中的Generator函数

最近在学习redux-saga,因为redux-saga须要使用Generator函数,因此下来就回顾了一下Generatorjavascript

Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数彻底不一样java

写法上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方法redux

let g = demo()异步

此时若咱们第一次调用async

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依次会打印出 1十一、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有什么优点^_^

相关文章
相关标签/搜索