持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情
1.原因
ES6 诞生以前,异步编程的方法,大概有:回调函数、事件监听、发布/订阅和Promise 对象,Generator 函数将 JavaScript 异步编程带入了一个全新的阶段。
它可以作为异步编程的完整解决方案,主要有两点:
Generator 函数可以暂停执行和恢复执行(根本原因);
整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用yield语句注明
函数体内外的数据交换和错误处理机制。
上面代码的最后一行,Generator 函数体外,使用指针对象的throw方法抛出的错误,可以被函数体内的try...catch代码块捕获。这意味着,出错的代码与处理错误的代码,实现了时间和空间上的分离,这对于异步编程无疑是很重要的。
1.Thunk 函数
概念:在 JavaScript 语言中,Thunk 函数替换的不是表达式,而是多参数函数,将其替换成一个只接受回调函数作为参数的单参数函数。
上面代码中,fs模块的readFile方法是一个多参数函数,两个参数分别为文件名和回调函数。经过转换器处理,它变成了一个单参数函数,只接受回调函数作为参数。这个单参数版本,就叫做 Thunk 函数。
Thunk 函数的自动流程管理
Thunk 函数真正的威力,在于可以自动执行 Generator 函数
上面代码的run函数,就是一个 Generator 函数的自动执行器。内部的next函数就是 Thunk 的回调函数。next函数先将指针移到 Generator 函数的下一步(gen.next方法),然后判断 Generator 函数是否结束(result.done属性),如果没结束,就将next函数再传入 Thunk 函数(result.value属性),否则就直接退出
1.Generator函数的流程管理
Generator 函数gen会自动执行完所有步骤,但是,这不适合异步操作。如果必须保证前一步执行完,才能执行后一步,上面的自动执行就不可行。这时,Thunk 函数就能派上用处
变量g是 Generator 函数的内部指针,表示目前执行到哪一步。next方法负责将指针移动到下一步,并返回该步的信息(value属性和done属性),仔细查看上面的代码,可以发现 Generator 函数的执行过程,其实是将同一个回调函数,反复传入next方法的value属性
1.co 模块
概念:co 模块是著名程序员 TJ Holowaychuk 于 2013 年 6 月发布的一个小工具,用于 Generator 函数的自动执行。
例子:
一个 Generator 函数,用于依次读取两个文件
co 模块可以让你不用编写 Generator 函数的执行器。
上面代码中,Generator 函数只要传入co函数,就会自动执行。
co函数返回一个Promise对象,因此可以用then方法添加回调函数。
处理并发的异步操作。