Generator 函数的异步应用

95 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

1.原因

ES6 诞生以前,异步编程的方法,大概有:回调函数、事件监听、发布/订阅和Promise 对象,Generator 函数将 JavaScript 异步编程带入了一个全新的阶段。

它可以作为异步编程的完整解决方案,主要有两点:

Generator 函数可以暂停执行和恢复执行(根本原因);

image.png

整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用yield语句注明

函数体内外的数据交换和错误处理机制。

image.png

上面代码的最后一行,Generator 函数体外,使用指针对象的throw方法抛出的错误,可以被函数体内的try...catch代码块捕获。这意味着,出错的代码与处理错误的代码,实现了时间和空间上的分离,这对于异步编程无疑是很重要的。

1.Thunk 函数

概念:在 JavaScript 语言中,Thunk 函数替换的不是表达式,而是多参数函数,将其替换成一个只接受回调函数作为参数的单参数函数。

image.png

上面代码中,fs模块的readFile方法是一个多参数函数,两个参数分别为文件名和回调函数。经过转换器处理,它变成了一个单参数函数,只接受回调函数作为参数。这个单参数版本,就叫做 Thunk 函数。  

Thunk 函数的自动流程管理

Thunk 函数真正的威力,在于可以自动执行 Generator 函数

image.png

上面代码的run函数,就是一个 Generator 函数的自动执行器。内部的next函数就是 Thunk 的回调函数。next函数先将指针移到 Generator 函数的下一步(gen.next方法),然后判断 Generator 函数是否结束(result.done属性),如果没结束,就将next函数再传入 Thunk 函数(result.value属性),否则就直接退出

1.Generator函数的流程管理

image.png

Generator 函数gen会自动执行完所有步骤,但是,这不适合异步操作。如果必须保证前一步执行完,才能执行后一步,上面的自动执行就不可行。这时,Thunk 函数就能派上用处

image.png

变量g是 Generator 函数的内部指针,表示目前执行到哪一步。next方法负责将指针移动到下一步,并返回该步的信息(value属性和done属性),仔细查看上面的代码,可以发现 Generator 函数的执行过程,其实是将同一个回调函数,反复传入next方法的value属性

1.co 模块

概念:co 模块是著名程序员 TJ Holowaychuk 于 2013 年 6 月发布的一个小工具,用于 Generator 函数的自动执行。

例子:

一个 Generator 函数,用于依次读取两个文件

image.png

co 模块可以让你不用编写 Generator 函数的执行器。

image.png

上面代码中,Generator 函数只要传入co函数,就会自动执行。

image.png

co函数返回一个Promise对象,因此可以用then方法添加回调函数。

处理并发的异步操作。