《深入理解Docker》 筆記
async 函式是什麼?一句話,它就是 Generator 函式的語法糖,使得非同步操作變得更加方便。
基本使用
const fs = require("fs"); const readFile = function(url){ return new Promise((resolve,reject)=>{ fs.readFile(url,(err,content)=>{ if(err){ reject(err) return; } resolve(content.toString()) }) } ) }async function files(){ const data1 = await readFile("./text.txt"); const data2 = await readFile("./text2.txt"); const data3 = await readFile("./text3.txt"); console.log(data1); console.log(data2); console.log(data3); } files() console.log("我執行了");
此時輸出是非同步執行的
發現上面files函式中await語句後面的readFile沒有使用.then,也能返回結果,此時和我們加then的效果是一樣的
const fs = require("fs"); const readFile = function(url){ return new Promise((resolve,reject)=>{ fs.readFile(url,(err,content)=>{ if(err){ reject(err) return; } resolve(content.toString()) }) } ) } async function files(){ constdata1 = await readFile("./text.txt").then((data)=>{ console.log(data); return readFile("./text2.txt") }).then((data)=>{ console.log(data); return readFile("./text3.txt") }).then((data)=>{ console.log(data) }).catch((err)=>{ console.log(err) }) } files() console.log("我執行了");
任何一個函式都能加async這個關鍵詞,表示這個函式內部要書寫非同步程式碼
async表示定義當前的函式為一個非同步函式,await只能用在async定義的函式內有效,表示等待非同步讀取的結果,如果在普通函式中會報錯
此時函式內部是如何執行的?
const fs = require("fs"); const readFile = function(url){ return new Promise((resolve,reject)=>{ fs.readFile(url,(err,content)=>{ if(err){ reject(err) return; } resolve(content.toString()) }) } ) } async function files(){ const data1 = await readFile("./text.txt"); console.log("我在data1中"); console.log(data1); const data2 = await readFile("./text2.txt"); console.log("我在data2中"); console.log(data2); const data3 = await readFile("./text3.txt"); console.log("我在data3中"); console.log(data3); } files() console.log("我執行了");
此時會發現先輸出我執行了,表示當前整個函式是非同步的,然後函式體內部是按照同步程式碼執行的,也就是await將非同步語句變為了同步語句在執行
async函式
async函式返回一個Promise物件
此時可以通過then來呼叫獲取值
函式內部丟擲錯誤,會導致返回的Promise物件變為reject狀態。丟擲的錯誤物件會被catch方法回撥函式接收到。
await命令
await命令後面是一個Promise物件。如果不是,會被轉成一個立即resolve的Promise物件。也就是說,如果不是promise物件,此時函式內部返回的時候會自動包一個promise的殼子
await命令後面的Promise物件如果變為reject狀態,則reject的引數會被catch方法的回撥函式接收到。
async函式的錯誤機制問題
可以通過try-catch來進行錯誤機制的處理
async函式的多種使用形式
// 函式宣告 async function fun() {} // 函式表示式 const fun = async function () {}; // 物件的方法 let obj = { async fun() {} }; obj.fun().then(...) // Class 的方法 class Storage { constructor() { this.cachePromise = caches.open('avatars'); } async getAvatar(name) { const cache = await this.cachePromise; return cache.match(`/avatars/${name}.jpg`); } } const storage = new Storage(); storage.getAvatar('jake').then(...); // 箭頭函式 const fun = async () => {};
for await...of遍歷非同步
for await...of
語句建立一個迴圈,該迴圈遍歷非同步可迭代物件以及同步可迭代物件,包括:內建的String
,Array
,類似陣列物件 (例如arguments
或NodeList
),TypedArray
,Map
,Set
和使用者定義的非同步/同步迭代器。它使用物件的每個不同屬性的值呼叫要執行的語句來呼叫自定義迭代鉤子。
類似於await
運算子一樣,該語句只能在一個async function內部使用。
語法:
for await (variable of iterable) { //statement }
variable
在每次迭代中,將不同屬性的值分配給變數。變數有可能以const
,let
, 或者var
來宣告。
iterable
被迭代列舉其屬性的物件。與 for...of 相比,這裡的物件可以返回Promise
,如果是這樣,那麼variable
將是Promise
所包含的值,否則是值本身。
迭代非同步可迭代物件
var asyncIterable = { [Symbol.asyncIterator]() { return { i: 0, next() { if (this.i < 3) { return Promise.resolve({ value: this.i++, done: false }); } return Promise.resolve({ done: true }); } }; } }; (async function() { for await (num of asyncIterable) { console.log(num); } })();
迭代非同步生成器
async function* asyncGenerator() { var i = 0; while (i < 3) { yield i++; } } (async function() { for await (num of asyncGenerator()) { console.log(num); } })();