Skip to content

异步编程-Generator

date: 2020-05-30 16:46:12 tags: [js, 异步编程]

协程

传统的编程语言,早有异步编程的解决方案(其实是多任务的解决方案)。其中有一种叫做"协程"(coroutine),意思是多个线程互相协作,完成异步任务。 协程有点像函数,又有点像线程。它的运行流程大致如下。

  1. 协程A开始执行
  2. 协程A执行到一半,进入暂停,执行权转移到协程B
  3. (一段时间后)协程B交还执行权
  4. 协程A恢复执行
上面流程的协程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);
});

京ICP备2024093538号-1