本文是V8引擎详解系列的第九篇,重点内容是关于生成器函数的运做机制,以及协程的概念。文末会有已经完成的系列文章的连接,本系列文章还在不断更新欢迎持续关注。javascript
在Javascript最初的规则中中,一个函数开始执行后,就会运行到最后或遇到return时结束,运行期间不会有其它代码可以打断它。而ES6中引入的Generator(生成器)函数打破了这个规则,Generator函数能够交出函数的执行权(暂停执行),这也是和普通函数最大的区别。
先说一下Generator的几个特色:html
经过一小段代码来看一下Generator函数java
function* gen() {
yield 'first';
yield 'second';
yield 1 + 2;
return 'end';
}
let g = gen();
g.next(); // {value: 'first', done: 'false'};
g.next(); // {value: 'second', done: 'false'};
g.next(); // {value: '3', done: 'false'};
g.next(); // {value: 'end', done: 'true'};
复制代码
用起来也很简单,经过构建函数 yiled 构建阶段状态,调用时经过调用next返回当前状态的信息(value)以及执行状态(done)。也正是经过Generator函数和Promise的结合完全解决了回调地狱的问题,并于ES7规范推出了官方语法糖async/await。
本文主要来聊聊Generator函数究竟是如何实现的。缓存
想要了解协程就要先了解进程与线程的概念(这几个概念在计算机中都是属于比较抽象的概念也历来没有统一的标准定义,因此下面只表明我的的观点与理解)。bash
进程最基本的能力就是 被操做系统调度 以及 进行资源分配和调度,做为一个调度资源的基本单位若是想要同一时间同时干两件事情,因而诞生了 线程 的概念。并发
线程经过如下特色来帮助进程能够在同一时间完成多件事情:async
以上即是进程和线程的基本概念,若是以为我说的仍是比较抽象,能够参考一下阮大大的进程与线程的一个简单解释来帮助理解。函数
Generator函数 本质上就是协程的一种实现,若是你能理解协程是什么那么你就能轻松的理解Generator函数。高并发
协程是一种比线程更加轻量级的存在。你能够把协程当作是跑在线程上的任务,一个线程上能够存在多个协程,可是在线程上同时只能执行一个协程。post
协程概念的提出比较早,单核CPU场景中发展出来的概念,经过提供挂起和恢复接口,实如今单个CPU上交叉处理多个任务的并发功能。
那么本质上就是在一个线程的基础上,增长了不一样任务栈的切换,经过不一样任务栈的挂起和恢复,线程中进行交替运行的代码片断,实现并发的功能。(注意是并发不是并行)
多个线程之间调用资源时会发生竞争关系,会致使锁的竞争,由于协程自己就是单核cpu上进行操做(在一个线程上同时只能执行一个协程),因此不存在竞争关系。
协程的每一个任务栈的占用的内存空间远比线程小,在高并发场景,线程太多也会致使OOM
协程的切换(挂起和恢复)彻底由用户控制,不须要系统进行切换,成本极低。
ES6中引入的生成器函数,就是给用户提供了协程特性的入口,经过生成器函数让咱们可使用协程的特性。
这些特性使得程序更适合高并发的I/O操做,更容易的真正解决了回调地狱的问题。
本文主要了解了关于生成器函数的运做机制,以及协程的概念,若是你以前以为不够理解生成器函数,读完本文会发现其实本质上生成器函数不难理解,只要能够理解协程的概念,也就能明白为何会出现生成器函数。若是有什么错误,请在评论中和做者一块儿讨论,若是您以为本文对您有帮助请帮忙点个赞,感激涕零。
V8引擎详解(一)——概述
V8引擎详解(二)——AST
V8引擎详解(三)——从字节码看V8的演变
V8引擎详解(四)——字节码是如何执行的
V8引擎详解(五)——内联缓存
V8引擎详解(六)——内存结构
V8引擎详解(七)——垃圾回收机制
V8引擎详解(八)——消息队列
V8引擎详解(九)——协程&生成器函数