在js中,一个函数一旦开始执行,就会运行到最后或遇到return时结束,运行期间不会有其它代码能够打断它,也不能从外部再传入值到函数体内
而Generator函数的出现使得打破函数的完整运行成为了可能
generator函数为处理异步编程提供了解决方法(异步函数),内部封装了大量的状态,允许我们逐条遍历
语法:function *demo() { 函数中定义状态 }
在函数内部通过yield关键字定义状态,yield表示暂停的意思
注意:yield关键字只能出现在generator函数中
通过return定义最后一个状态,return后面的状态不会执行
generator函数的返回值实现了next方法,因此可以通过next方法逐条遍历内部的状态
next方法的返回值是一个对象
done属性: 表示是否遍历完成 value属性: 表示状态值
next 方法返回的状态对象
如果有状态的情况下,done是fasle,value是状态值
如果没有状态,此时,done是true,value是undefined
generator函数的返回值也实现了迭代器接口,因此也可以通过for of方式遍历内部的状态
但是不要同时使用两种方式去遍历内部的状态 因为,一方遍历完成,另一方就得不到状态了
当generator函数遍历完成之后,此时它的状态变为closed
当generator函数没有遍历完成的时候,此时它的状态变为suspended
<script> function *day() { // 定义状态 yield '起床'; yield '吃饭'; yield '工作'; yield '下班'; yield '吃晚饭'; // 最后一个状态可以通过return来定义 // 注意遍历到return这个状态的时候,done属性也是true return '睡觉'; } let t = day(); console.log(t); // day {<suspended>} 返回一个t的对象 suspended表示没有遍历完成的状态
可以看出generator函数和普通函数不一样 普通函数调用立即执行并输出返回值 而generator函数返回一个对象 // console.log(t.next()) console.log(t.next()) console.log(t.next()) console.log(t.next()) console.log(t.next()) console.log(t.next()) console.log(t.next()) // for(let item of t) { // // 可以访问yield状态,无法访问return状态 // console.log(item) // } // 一旦遍历完成,只能重新创建再遍历 var d2 = day(); console.log(d2.next()); console.log(d2.next()); </script>
generator函数是异步函数,可以让异步操作一个接一个的触发
function *tast() { yield setTimeout(() => { console.log(1) }, 1000) yield setTimeout(() => { console.log(2); }, 2000) yield setTimeout(() => { console.log(3); }, 3000) } // 做这些异步操作 let t = tast(); t.next() t.next()
generator 函数的数据传递
在generator函数中数据传递有两个方向:
数据由generator函数的内部流向外部
1 通过yield表达式定义状态值
2 在外部通过next方法返回的对象中的value属性获取
数据由generator函数的外部流向内部
1 在外部通过next方法传递数据 (第一次执行next方法,不需要传递参数)
2 在内部通过yield表示式接收数据 (想让第一个yield关键字接收数据,要给第二个next方法传递参数)
return
在generator函数的原型中提供了return方法,用于在外部停止内部状态的遍历
如果在函数体中出现了finally语法,return语句将会延后执行(也就是说return不能终止finally中的语句)
throw
在generator函数的原型中提供了throw方法,允许在外部抛出错误
为了代码正常执行,我们可以在状态函数体中通过try catch语句去捕获错误
如果外部抛出两个错误:
第一个错误在状态函数体中通过try catch语句去捕获第一个错误
第二个错误在状态函数体外部通过try catch语句去捕获第二个错误
yield*
可以将函数内部的状态复制到另一个函数体中执行
三个点语法
使用三个点语法解构的时候,可以将一个状态函数体中的所有状态值获取到
generator 函数的 this
在generator函数中的this指向window 所以,不能通过this去添加任何的属性以及方法
如果想要添加属性或者方法,我们可以在函数执行的时候,使用call或者是apply方法改变其作用域, 将指向函数的原型