Appearance
异步编程-Generator
date: 2020-05-30 16:46:12 tags: [js, 异步编程]
协程
传统的编程语言,早有异步编程的解决方案(其实是多任务的解决方案)。其中有一种叫做"协程"(coroutine),意思是多个线程互相协作,完成异步任务。 协程有点像函数,又有点像线程。它的运行流程大致如下。
- 协程A开始执行
- 协程A执行到一半,进入暂停,执行权转移到协程B
- (一段时间后)协程B交还执行权
- 协程A恢复执行
Generator的概念
Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。
bash
function* gen(x){
var y = yield x + 2;
return y;
}
// 执行
var g = gen(1);
g.next(); // {value: 3, done: false}
g.next(); // { value: undefined, done: true }上面代码就是一个 Generator 函数。它不同于普通函数,是可以暂停执行的,所以函数名之前要加星*,以示区别。 上面代码中,调用 Generator 函数,会返回一个内部指针(即遍历器 )g 。这是 Generator 函数不同于普通函数的另一个地方,即执行它不会返回结果,返回的是指针对象。调用指针 g 的 next 方法,会移动内部指针(即执行异步任务的第一段),指向第一个遇到的 yield 语句,上例是执行到 x + 2 为止。
换言之,next 方法的作用是分阶段执行 Generator 函数。每次调用 next 方法,会返回一个对象,表示当前阶段的信息( value 属性和 done 属性)。value 属性是 yield 语句后面表达式的值,表示当前阶段的值;done 属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段。
调用方法
下面看看如何使用 Generator 函数,执行一个真实的异步任务。
bash
function* gen(x){
var y = yield x + 2;
return y;
}
// 执行
var g = gen(1);
g.next(); // {value: 3, done: false}
g.next(); // { value: undefined, done: true }上面代码中,Generator 函数封装了一个异步操作,该操作先读取一个远程接口,然后从 JSON 格式的数据解析信息。就像前面说过的,这段代码非常像同步操作,除了加上了 yield 命令。 执行这段代码的方法如下。
bash
var g = gen();
var result = g.next();
result.value.then(function(data){
return data.json();
}).then(function(data){
g.next(data);
});