js異步之async和await實現同步寫法
首先我們假設有一方法 readFile 可以讀取文件內容, 但是它是異步的。
var gen = function* (){ var a = yield readFile('./a.txt'); console.log(a.toString()); var b = yield readFile('./b.txt'); console.log(b.toString()); };
首先我們看下上面的代碼,如果我們將function 後面的 * 改成 async,將yield 改成 await,也就是下面的代碼
var gen = function async (){ var a = await readFile('./a.txt'); console.log(a.toString()); var b = await readFile('./b.txt'); console.log(b.toString()); };
是不是就是我們想要的同步寫異步操作瞭,第一種寫法就是 es6 中新支持的特性,Generator 函數,那什麼是 Generator 函數呢,簡單來說Generator 函數有多種理解角度。語法上,首先可以把它理解成,Generator 函數是一個狀態機,封裝瞭多個內部狀態。執行 Generator 函數會返回一個遍歷器對象,也就是說,Generator 函數除瞭狀態機,還是一個遍歷器對象生成函數。返回的遍歷器對象,可以依次遍歷 Generator 函數內部的每一個狀態。上面的官方解釋看不懂沒關系。我們下面用例子演示下。
function* func(){ console.log("one"); yield '1'; console.log("two"); yield '2'; console.log("three"); return '3'; } var f = func(); f.next(); // one // {value: "1", done: false} f.next(); // two // {value: "2", done: false} f.next(); // three // {value: "3", done: true} f.next(); // {value: undefined, done: true}
上面的代碼我們第一次調用 f.next() 時,函數 func 開始執行,並在執行到第一個 yield 時停住,並返回 yield 後面表達式的值,格式就是 {value: "1", done: false} 這種格式,value就是 yield 表達式的值
done 表示func函數是否執行完畢,此時如果我們如果接著調用 f.next(),類推將返回第二 yield 後面表達式的值,也就是 {value: "2", done: false}。我們可以繼續調用 f.next() 直至 done 變成 true, 它表示func函數執行完瞭。
function* func(){ var a = yield '1'; console.log(a); var b = yield '2'; console.log(b); } var f = func(); f.next(); f.next('1');
f.next('2');我們繼續改造 func 函數為上面這種,在 next 分別傳入 1 和 2,我們會發現 console.log(a) 打印 1 ,console.log(b) 打印 2,也就是我們可以傳值到 Generator 函數中。
現在我們回到下面這段代碼上面來,然後重新設計下,並實現 readFile 函數。
var gen = function* (){ var a = yield readFile('./a.txt'); console.log(a.toString()); var b = yield readFile('./b.txt'); console.log(b.toString()); }; var readFile = function (fileName){ return new Promise((resolve)=>{ fs.readFile(fileName, (err, data)=>{ resolve(data); }) }); }; function run(fn) { var gen = fn(); function next(data) { var result = gen.next(data); if (result.done) return; result.value.then((data)=>{ next(data); }) } next(); } run(gen);
看上面的代碼我們用 promise 實現 readFile 函數,此時我們 yield 的返回值就是一個 promise 對象瞭,我們就可以使用, result.value.then((data)=>{next(data);})
將 yield 返回的 value 值重新傳回 Generator 函數,這樣我們的 console.log(a.toString()); 就可以獲取到 a.txt 文件中的內容瞭, if (result.done) return; 可以用瞭判斷 Generator 函數 是否已執行完畢,用來結束循環調用。所以如果我們單獨去看 gen 函數,是不是就是將異步操作寫成同步語法瞭,如果我們將function 後面的 * 改成 async,將yield 改成 await也就是我們常用語法瞭。
到此這篇關於js異步之async和await實現同步寫法的文章就介紹到這瞭,更多相關js async和await同步內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- JavaScript Generator異步過度的實現詳解
- await-to-js源碼深入理解處理異步任務用法示例
- JavaScript詳解使用Promise處理回調地獄與async await修飾符
- 詳解ES9的新特性之異步遍歷Async iteration
- es7中的async、await使用方法示例詳解