最近在学习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}
根据结果咱们能够很清楚的看到当返回值的done
为true
的时候就表明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有什么优点^_^