一,前言
上一篇,实现了 promisify 和应用场景介绍,主要涉及以下几个点:
- promisify 简介和测试;
- promisify 功能的实现:promisify、promisifyAll;
目前,Promise 部分已基本完成,Promise 仅仅是对异步回到进行了优化,在 Promise 的内部依然还是回调,所以并没有解决“回调地狱”的问题;
最终解决方案还要使用 async/await,async/await 是基于 generator 的语法糖,而为了搞清楚 async/await 的原理,需要先对 generator、co 进行了解;
本篇,介绍 generator 生成器;
二,generator 简介
1,什么是 generator
- Generator 函数是 ES6 提供的一种异步编程解决方案
- Generator 函数,可以理解为一个状态机,内部封装多个状态,返回 Iterator 迭代器对象;
2,generator 的特征
- 星函数:function 关键字与函数名之间有一个星号;
- yield 表达式(意为“产出”):函数体内部使用 yield 语句,定义不同的内部状态;
- 暂停执行功能:yield 表达式具有暂停执行的功能,通过 next 方法可以恢复执行;
- next 方法:每调用一次 next 方法,就会从暂停处继续执行到下一个 yield 表达式为止;
因此,generator 可以把函数的执行权交给外部控制
3,generator 的使用
// 生成器函数: 返回 Iterator 迭代器
function * read(){ // 星函数
console.log(1)
yield 1; // 代码执行遇到 yield 讲终止执行,外部调用 next 后继续
console.log(2)
yield 2;
console.log(3)
yield 3;
}
// 执行生成器函数,返回一个迭代器
let it = read();
it.next();// 走下一步逻辑 执行结果:1
it.next();// 走下一步逻辑 执行结果:2
it.next();// 走下一步逻辑 执行结果:3(此时虽然都走完了,但还需要在 next 一次才能知道)
it.next();// 已全部执行完成
4,generator 的功能分析
根据以上 generator 生成器函数的特性,即:代码的执行可以通过外部函数进行分步控制;
这是一个有限状态机:while(1){switch...case...}
三,generator 实现
1,generator 执行分析
babeljs: babel 能够将低级语法转换成为高级语法;
将之前示例进行转化:
右侧代码:
"use strict";
var _marked = /*#__PURE__*/regeneratorRuntime.mark(read);
function read() {
return regeneratorRuntime.wrap(function read$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
console.log(1);
_context.next = 3;
return 1;
case 3:
console.log(2);
_context.next = 6;
return 2;
case 6:
console.log(3);
_context.next = 9;
return 3;
case 9:
case "end":
return _context.stop();
}
}
}, _marked);
}
var it = read();
it.next();
it.next();
it.next();
it.next();
代码分析:
while(1)
:表示有限状态机,内部的switch...case...
会被执行多次;_context.prev
:是代码的执行指针,会根据指针逐层地向下依次执行;- 第一次
_context.next = 0
后,_context.prev
被赋值为 0, 执行 case 0 的逻辑;执行完成后_context.next = 2
,继续再执行执行 case 2 的逻辑…直至最后调用_context.stop()
完成;
四,结尾
本篇,主要介绍了 generator 生成器函数的使用和实现原理,主要涉及以下几个点:
- generator 简介:特性、用法、功能分析;
- generator 实现原理分析;
下篇,继续介绍 co 库:自动执行 Generator 生成器函数;