Generator
函数之所以可以用于异步操作是因为yield
关键字,Generator
函数在执行过程中遇到yield
语句时就会暂停执行,并返回yield
语句后面的内容,要想继续执行后续的代码就需要手动调用next
方法。这样就找到了顺序执行异步操作的方法了,也就是将所有异步操作都放在yield
关键字后面,同时在异步操作内配置相应的next
方法,以便在异步操作结束后返回出操作的结果并交出执行权,来看下面这个例子,我们要读取多个文件的内容并输出,但是要求是必须先读完a.txt
中的内容,打印出来以后再读取b.txt
,最后是c.txt
的内容,一般的回调写法如下:

callback hell
不利于代码维护,那么用Generator
函数怎么写呢?

read
函数中设置了setTimeout
以便观察读取的先后顺序(因为文件都很小,读取速度太快),执行结果如下图所示:

read
函数,再在reader
这个Generator
函数中调用他,从而达到了将异步操作写成了同步的形式,避免了callback hell
现象,即使读取再多的文件也不会出现横向发展,但是主要缺点就在于需要自己去封装这样一个read
函数,因为Generator
函数中的yield
只负责将执行权交出,而具体什么时候拿回执行权就需要人为控制,这也是为什么koa2
中用async
函数取代Generator
函数的原因之一吧。现在来分析一下封装的过程:
将读取文件的异步操作放进
read
函数中,等到读取操作结束时在内部调用next
方法使Generator
函数进行下一步操作,同时传出读取的内容。如果不封装的话就无法确定后面操作的顺序,如下:



网友评论