5分鐘搞懂 ES8 非同步函數原理

程序閉嘴不說話系列

本篇假設大家已經看了:十五行代碼帶你搞懂Promise,11行代碼帶你搞懂 Generator 函數

// 先聲明一個函數,模擬非同步調用n// 她是我們的睡美人,一定時間之後會睡醒nfunction sleep(ms){n // 沒錯,睡美人要準備開始睡覺了n // 不過睡之前先給大家一個允諾:我會醒來的 n return new Promise((resolve,reject) => {n // 睡前先記錄下當前時間n let begin = new Date()n setTimeout(() => {n // 睡美人要睡醒了n // 同時返回自己實際睡了多長時間n resolve(new Date() - begin)n }, ms)n })n}nn// 為了簡化回調寫法,我們使用 Generator 函數進行非同步控制nfunction* 調戲睡美人(){n // 記錄下睡美人實際睡了多久n let totalTime = 0n console.log(睡美人睡覺)n totalTime += yield sleep(1000)n console.log(睡美人第一次睡醒了)n console.log(讓她再睡一會吧)n totalTime += yield sleep(2000)n console.log(睡美人第二次睡醒了)n console.log(`睡美人實際睡了${totalTime}ms`)n console.log(偷偷親一口,然後跑了)n}nn// 想要成功的調戲睡美人n// 我們可以靠自己的雙手nlet it = 調戲睡美人()nn// 先使用 it.next() 執行到睡美人第一次睡覺的地方(也就是yield sleep(1000)的地方)n// it.next().value 其實是 sleep 返回的那個 Promisen// 調用 then() 設置 Promise 執行成功後的回調函數n// data 為非同步調用結果nit.next().value.then((data) => {n // 需要讓 Generator 繼續執行n // 同理,我們也需要綁定 Promise 執行成功後的回調函數n // 並把上次非同步執行的結果傳入 Generator 函數內n it.next(data).value.then((data) => {n // 想什麼呀,肯定繼續執行呀n it.next(data)n })n})nn// 每次調戲睡美人都需要寫好多代碼呀n// 寫的我都喪失性趣,哦不,是興趣了n// 有沒有辦法自動幫我們調戲睡美人?n// 有的!看我乾坤大法nfunction run(gen){n // 獲取 Generator 執行"指針"n let it = gen()n // 聲明一個函數,每次 Promise 執行完都會回調這個函數n function next(data){n // 獲取執行結果n let result = it.next(data)n // 如果完成了,我們就沒必要繼續執行了n if (result.done) return result.valuen // 否則,我們就要繼續綁定回調函數了n result.value.then(data => {n // 沒錯,調用自己,和遞歸差不多n next(data)n })n }n // 我們要先啟動一下,可愛的乾坤大法才可以發揮威力n next()n}nn// 以後我們就可以這樣調戲睡美人了n// 好方便,有木有?nrun(調戲睡美人)nn// 如果把 function* 換成 async functionn// yield 換成 awaitn// 就是 ES7 中的 async/await 語法n// 也就是說 async/await 其實就是 Generator 函數的語法糖n


歡迎加入碼蜂社前端交流 3 群: 583594212

掃描下方二維碼或搜索「碼蜂社」公眾號,不怕錯過好文章:

推薦閱讀:

這是我做的遊戲,我可以勝任前端工程師么?
12個前端初學者必學技能
前端每周清單第9期:向重度jQuery介紹Vue;React Studio 1.0.2、ECharts GL 1.0 alpha、Prettier 1.0發布
前端工程師做事的三重境界:我的進階之路

TAG:前端开发 | 前端工程师 | ECMAScript2015 |