本文是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
進程最基本的能力就是 被操做系統調度 以及 進行資源分配和調度,是一個調度資源的基本單位。
做爲一個調度資源的基本單位但願能夠同一時間幹多件事情,因而誕生了 線程 的概念。markdown
線程經過如下特色來幫助進程能夠在同一時間完成多件事情:併發
以上即是進程和線程的基本概念,若是以爲我說的仍是比較抽象,能夠參考一下阮大大的進程與線程的一個簡單解釋來幫助理解。async
Generator函數 本質上就是協程的一種實現,若是你能理解協程是什麼那麼你就能輕鬆的理解Generator函數。函數
協程是一種比線程更加輕量級的存在。你能夠把協程當作是跑在線程上的任務,一個線程上能夠存在多個協程,可是在線程上同時只能執行一個協程。高併發
協程概念的提出比較早,單核CPU場景中發展出來的概念,經過提供掛起和恢復接口,實如今單個CPU上交叉處理多個任務的併發功能。
那麼本質上就是在一個線程的基礎上,增長了不一樣任務棧的切換,經過不一樣任務棧的掛起和恢復,線程中進行交替運行的代碼片斷,實現併發的功能。(注意是併發不是並行)
多個線程之間調用資源時會發生競爭關係,會致使鎖的競爭,由於協程自己就是單核cpu上進行操做(在一個線程上同時只能執行一個協程),因此不存在競爭關係。
協程的每一個任務棧的佔用的內存空間遠比線程小,在高併發場景,線程太多也會致使OOM
協程的切換(掛起和恢復)徹底由用戶控制,不須要系統進行切換,成本極低。
ES6中引入的生成器函數,就是給用戶提供了協程特性的入口,經過生成器函數讓咱們可使用協程的特性。
這些特性使得程序更適合高併發的I/O操做,更容易的真正解決了回調地獄的問題。
本文主要了解了關於生成器函數的運做機制,以及協程的概念,若是你以前以爲不夠理解生成器函數,讀完本文會發現其實本質上生成器函數不難理解,只要能夠理解協程的概念,也就能明白爲何會出現生成器函數。若是有什麼錯誤,請在評論中和做者一塊兒討論,若是您以爲本文對您有幫助請幫忙點個贊,感激涕零。
V8引擎詳解(一)——概述
V8引擎詳解(二)——AST
V8引擎詳解(三)——從字節碼看V8的演變
V8引擎詳解(四)——字節碼是如何執行的
V8引擎詳解(五)——內聯緩存
V8引擎詳解(六)——內存結構
V8引擎詳解(七)——垃圾回收機制
V8引擎詳解(八)——消息隊列
V8引擎詳解(九)——協程&生成器函數