詳解ES6中的三種異步解決方案
前置知識(shí)準(zhǔn)備
- Generator 函數(shù) 執(zhí)行會(huì)返回一個(gè)迭代器(Iterator), 在迭代器上可以調(diào)用 next() 方法, 執(zhí)行下一個(gè) yield 或 return
- 調(diào)用 next() 方法,會(huì)返回一個(gè)對(duì)象 {value: res, done: false} , value 的值 為 yield 之后表達(dá)式的值,done 的值 表示迭代器,是否已經(jīng)執(zhí)行完畢(最后一個(gè)yield 或 return )
- next() 方法,可以傳入一個(gè)值,做為前一個(gè)yield 表達(dá)式的返回值
有了這些知識(shí),可以把Promise 對(duì)象 做一個(gè)的 yield 的值,配合一個(gè)執(zhí)行器,來(lái)處理異步操作
方式一: Generator + Promise + 執(zhí)行器
const fs = require('fs') // Promise 版的readFile const readFile = function (fileName) { return new Promise(function(resolve, reject) { fs.readFile(fileName, function(err, data){ if (err) return reject(error); resolve(data); }) }) } const gen = function * () { let f1 = yield readFile('a.txt'); let f2 = yield readFile('b.txt'); console.log('F1--->', f1.toString()); console.log('F2--->', f2.toString()); } // 基于 Generator 和 Promise 的自動(dòng)執(zhí)行器 function run(gen) { let g = gen(); function next(data) { let result = g.next(data); if (result.done) return result.value; result.value.then(function(data) { next(data); }); } next(); } run(gen);
執(zhí)行器 中的 result.value 現(xiàn)在是一個(gè)Promise, 通過(guò) then 方法拿到需要的結(jié)果,傳下一次 next 方法,這樣 let f1 = yield readFile('a.txt'); 就可以拿到值!
方式二:Generator + Thunk函數(shù) + 執(zhí)行器
const fs = require('fs') // 把一個(gè)單一執(zhí)行的函數(shù) ,變成需要再次調(diào)用的函數(shù),固定一部分參數(shù) function thunkify(fn, obj = {}) { return function () { let args = Array.from(arguments); return function (m) { args.push(m) return fn.apply(obj, args) } } } const readFile = thunkify(fs.readFile, fs); const gen = function* () { let f1 = yield readFile('a.txt'); let f2 = yield readFile('b.txt'); console.log('F1-->', f1.toString()); console.log('F2-->', f2.toString()); } // 基于 Generator 和 Thunk函數(shù)的自動(dòng)執(zhí)行器 function run(fn) { let gen = fn(); function next(err, data) { let result = gen.next(data); if (result.done) return 1; result.value(next); } next(); } run(gen);
這里的 Thunk 轉(zhuǎn)換器,把原來(lái)的 fs.readFile 函數(shù) 轉(zhuǎn)換成需要兩次調(diào)用的函數(shù) ,readFile 的執(zhí)行結(jié)果,可以通過(guò)回調(diào)函數(shù)能參數(shù)傳遞出來(lái),再傳給 next 方法
方式三:基于 async 函數(shù) 和 await 的異步處理方式
const fs = require('fs') // Promise 版的readFile const readFile = function (fileName) { return new Promise(function(resolve, reject) { fs.readFile(fileName, function(err, data){ if (err) return reject(err); resolve(data); }) }) } const asyncReadFile = async function () { const f1 = await readFile('a.txt'); const f2 = await readFile('b.txt'); console.log(f1.toString()); console.log(f2.toString()); }; asyncReadFile();
readFile 函數(shù) 對(duì)比方式一沒(méi)有大的變化 ,Generator 函數(shù)變成 了 async 函數(shù),可見(jiàn) 這處方式 只是 方式一的一個(gè)語(yǔ)法糖,async 函數(shù)自帶了執(zhí)行器!
這個(gè)話題,還可以衍生出 yield 的更多用法 ,下次再寫(xiě),歡迎關(guān)注我!
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JS基于面向?qū)ο髮?shí)現(xiàn)的多個(gè)倒計(jì)時(shí)器功能示例
這篇文章主要介紹了JS基于面向?qū)ο髮?shí)現(xiàn)的多個(gè)倒計(jì)時(shí)器功能,結(jié)合實(shí)例形式分析了javascript面向?qū)ο蠹皶r(shí)間操作相關(guān)技巧,需要的朋友可以參考下2017-02-02JavaScript實(shí)現(xiàn)的級(jí)聯(lián)算法示例【省市二級(jí)聯(lián)動(dòng)功能】
這篇文章主要介紹了JavaScript實(shí)現(xiàn)的級(jí)聯(lián)算法,結(jié)合省市二級(jí)聯(lián)動(dòng)下拉菜單功能實(shí)例分析了javascript事件響應(yīng)與元素動(dòng)態(tài)操作實(shí)現(xiàn)級(jí)聯(lián)算法的相關(guān)技巧,需要的朋友可以參考下2018-12-12關(guān)于Ext中form移除textfield方法:hide(),setVisible(false),remove()
根據(jù)條件來(lái)控制是否顯示form里的textfield表單2010-12-12Bootstrap源碼解讀標(biāo)簽、徽章、縮略圖和警示框(8)
這篇文章主要源碼解讀了標(biāo)簽、徽章、縮略圖和警示框,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12JavaScript實(shí)現(xiàn)點(diǎn)擊單選按鈕改變輸入框中文本域內(nèi)容的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)點(diǎn)擊單選按鈕改變輸入框中文本域內(nèi)容的方法,涉及javascript單選按鈕控制頁(yè)面元素樣式的相關(guān)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-08-08鼠標(biāo)選擇動(dòng)態(tài)改變網(wǎng)頁(yè)背景顏色的JS代碼
這篇文章主要介紹了鼠標(biāo)選擇動(dòng)態(tài)改變網(wǎng)頁(yè)背景顏色的JS代碼,有需要的朋友可以參考一下2013-12-12JS實(shí)現(xiàn)橫向拉伸動(dòng)感伸縮菜單效果代碼
這篇文章主要介紹了JS實(shí)現(xiàn)橫向拉伸動(dòng)感伸縮菜單效果,涉及javascript基于定時(shí)函數(shù)及鼠標(biāo)事件操作頁(yè)面元素動(dòng)態(tài)變換的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09