异步编程的方法:
(1)回调函数
(2)事件监听
(3)发布/订阅
(4)Promise 对象
(5)新增:Generator 函数
-
协程的Generator 函数实现
协程 概念:多个线程互相合作,完成异步任务。
协程运行流程:
(1)协程 A 开始执行
(2)协程 A 执行到一半,进入到暂停,执行权转移到 协程 B
(3)一段时间后,协程 B 交还 执行权
(4)协程 A 恢复执行。
Generator 函数是协程在ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行 yield)。
整个 Genertaor 函数是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用yield 语句注明。
Generator 函数可以暂停执行和恢复执行,其次还有两个特性:函数体内外的数据交换(next()方法带参数,向Generator 函数体内输入数据)和错误处理机制(throw() 方法)
存在的问题:
Generator函数由于以上也想可以将异步操作简洁化,但存在问题是:即何时执行第一阶段,何时执行第二阶段问题上管理不方便。
解决办法:
Generator 函数是一个异步操作的容器,他的自动执行需要一种机制,当异步操作返回结果后,能够自动交回执行权。
两种方法:
(1)回调函数。将异步操作包装成 Thunk 函数,在回调函数里面交回执行权。
(2)Promise 对象。将异步操作包装成 Promise对象,用 then() 交回执行权。
-
Thunk 函数
Thunk 函数是自动执行 Generator 函数的一种方法。
扩充知识点:
参数的求值策略(即函数的参数到底应该何时求值):
(1)传值调用,即在进入函数体之前,计算参数的值,再将这个值传入函数。简单但是可能会造成性能损失。
(2)传名调用,即直接将参数表达式传入函数体,只在用到它的时候求值。
Thunk 函数的定义是一种传名调用的实现策略,用来替换某个表达式。
编译器"传名调用"实现往往是将参数放到一个临时函数之中,再将这个临时函数传入函数体。这个临时函数就叫做 Thunk 函数。
但在JavaScript 语言中是传值调用,其 Thunk 函数替换的不是表达式,而是多参数函数,将其替换成一个只接受回调函数作为参数的单参数函数。
任何函数,只要参数有回调函数,就可以写成 Thunk 函数的形式。
- Thunkify 模块 (生产环境的转换器)
###安装 thunkify 模块
npm install thunkify
###使用方法如下
var thunkify = require('thunkify');
var fs = require('fs');
var read = thunkify(fs.readFile);
read('package.json')(function(err,str){
//.....
});
-
Generator 函数的流程管理(Thunk函数实现)
-
co 模块
co 模块可以不用编写 Generator 函数的执行器。Generator 函数只要传入 co 函数,就会自动执行。
co 模块将两种自动执行器(Thunk 函数 和 Promise 对象)包装成一个模块。
使用 co 模块的前提条件:Generator 函数的yield 命令后面只能是 Thunk 函数或 Promise 对象。如果是数组或对象的成员,全部都是Promise 对象,也可以使用 co 模块。
(1)基于Promise 对象的自动执行
(2)处理并发的异步操作
co 模块支持并发的异步操作,即允许某些操作同时进行,等到他们全部完成,才进行下一步。
(3)处理 Stream