异步编程的 async/await
async/await 和 Generators + co 的寫法非常的相似,只是把用于聲明 Generator 函數的 * 關鍵字替換成了 async 并寫在了 function 關鍵字的前面,把 yield 關鍵字替換成了 await;另外,async 函數是基于 Promise 的,await 關鍵字后面等待的異步操作必須是一個 Promise 實例,當然也可以是原始類型的值,只不過這時的執行效果等同于同步,與 Generator 不同的是,await 關鍵字前可以使用變量去接收這個正在等待的 Promise 實例執行后的結果。
async 函數的基本用法
async 函數返回一個 Promise 實例,可以使用 then 方法添加回調函數。當函數執行的時候,只要遇到 await 就會等待,直到 await 后面的同步或異步操作完成,再接著執行函數體內后面的語句。
ES6的聲明
// 1- 函數聲明function * fn() {}// 2- 函數表達式const * fn = function() {};ES7的聲明
// 1- 函數聲明 async function fn() {}// 2- 函數表達式 const fn = async function() {};// 3- 箭頭函數 const fn = async () => {};// 4- 作為對象的方法 let obj = {async fn() {} };// 5- 作為 class 的方法 class Person(name) {constructor () {this.name = name;}async getName() {const name = await this.name;return name;} }使用 NodeJS 的 fs 模塊連續異步讀文件,第一個文件名為 a.txt,讀到的內容為 b.txt,作為要讀的第二個文件的文件名,繼續讀 b.txt 后將讀到的內容 “Hello world” 打印出來。
我們來使用 async/await 的方式來實現一下:
與 Generator 函數一樣,寫法像同步,執行是異步,不同的是我們即沒有手動調用 next 方法,也沒有借助 co 庫,其實是 async 函數內部集成了類似于 co 的執行器,幫我們在異步完成后自動向下執行代碼,所以說 async/await 是 Generators + co 的語法糖。
await 異步并發
在 async 函數中,如果有多個 await 互不依賴,這種情況下如果執行一個,等待一個完成,再執行一個,再等待完成,這樣是很浪費性能的,所以我們要把這些異步操作同時觸發。
假設我們異步讀取兩個文件,且這兩個文件不相關,我可以使用下面的方式來實現:
// 前置 let fs = require("fs"); let util = require("util"); let readFile = util.promisify(fs.readFile);// 方法1- 需要改進的 async 函數 async function fn() {let aData = await readFile("a.txt", "utf8");let bData = await readFile("b.txt", "utf8");return [aData, bData]; }fn();// 方法2- 在 async 函數外部觸發異步 let aDataPromise = readFile("a.txt", "utf8"); let bDataPromise = readFile("b.txt", "utf8");async function fn() {let aData = await aDataPromise;let bData = await bDataPromise;return [aData, bData]; }fn();// 方法3- 使用 Promise.all async function fn() {let dataArr = await Promise.all(readFile("a.txt", "utf8"),readFile("a.txt", "utf8"));return dataArr; }fn();異步并發實例
// 創建 Promise 實例 let p1 = Promise.resolve("p1 success"); let p2 = Promise.resolve("p2 success"); let p3 = Promise.resolve("p3 success");// 1-錯誤的處理方式 async 函數 async function fn(promises) {promise.forEach(function (promise) {await promise;}); }fn([p1, p2, p3]); // 執行時報錯// 2-正確的打開方式 修改方式 async function fn(promises) {for(let i = 0; i < promises.length; i++) {await promises[i];} }fn([p1, p2, p3]); // 正常執行總結
以上是生活随笔為你收集整理的异步编程的 async/await的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Iterator 遍历器的简单使用
- 下一篇: 函数返回对象写法的失误