generator(生成器)是ES6标准引入新的数据类型, 一个generator看上去像一个函数,但可以返回多次。
ES6中generator的定义借鉴了python的generator的概念和语法。
--------------------------------------------------------------------------------------------------------------
小插曲:所谓回调函数就是把任务的第二段单独写在一个函数里面,等到重新执行这个任务的时候,就直接调用这个函数。
为什么nodeJs约定,回调函数的第一个参数必须是错误对象err? 答:因为异步执行,分两段完成,如果在两段之间抛出错误,程序无法捕捉,只能当做参数传入第二段。
回调函数本身没有问题,它的问题出现在多个函数嵌套的回调函数噩梦。Promise 就是为了解决这个问题提出的。它不是新的语法功能,而是一种新的写法,允许将回调函数的横向加载改为纵向记载。采用promise连续读取多个文件。
promise提供then方法加载回调函数,catch方法捕捉执行中抛出的错误。所以promise方法只是回调函数的改进,使用then方法后,异步任务的两段执行看的更清楚了,除此之外,别无新意。然后promise最大的问题是代码冗余,原来的任务被promise包装了一下,一眼看上去都是一堆then,原来的语义变的很不清楚,那么是否有更好的写法?
传统的编程语言早就有异步编程的解决方案,其中有一种叫做协程,协程遇到yield命令就暂停,等到执行权返回,再从暂停的地方继续往后执行。它的最大优点,就是代码的写法非常像同步操作,如果去除yield命令,简直一模一样。
generator函数是协程在ES6的实现,最大特点是可以交出函数的执行权。generator不同于普通函数,是可以暂停的,所以函数名前面要加*号,以示区分。
整个generator函数就是一个封装的异步任务,或者说是异步任务的容器,异步操作需要暂停的地方都用yield注明。调用generator会返回一个内部指针,调用指针的next方法,会根据yield注明的地方分步执行。每次调用next都会返回一个对象,表示当前阶段的信息,value指yield后面表达式的值,done是一个布尔值 表示函数是否执行完毕。
generator函数可以暂停执行和恢复执行,这是它能封装异步任务的根本原因,除此之外它还有两个特性,使它可以作为异步编程的完整解决方案:函数体内外数据交换和错误处理机制。
next方法返回值的value属性,是generator向外输出数据,next方法还可以接受参数,是向generator内输入数据。
generator内部还可以部署错误处理代码,捕获generator外部抛出的错误。利用generator暂停执行和恢复执行,内外传值,报错捕获的特性,将异步任务封装起来,配合promiss代码更易于管理,更接近同步代码的书写格式。
Thunk-generator自动执行方案:
thunk,诞生在上世纪90年代,用于求值策略的传名调用,指将参数放到一个临时函数里,再将这个临时函数传入函数体,这个临时函数就叫做thunk. thunk是传名调用的一种实现策略,用来替代某个表达式。
js语言是传值调用,它的thunk函数含义有所不同,在js中thunk替代的不是表达式,而是多参数函数,将其替代成单参数版本,且只接受回调函数作为参数。
有了generator之后,thunk函数可以用于generator的自动流程管理。
async函数就是将generator的*号变成了async,将yield换成await,仅此而已。