好家伙,本篇為《JS高級程式設計》第十章“期約與非同步函數”學習筆記 ES8 的 async/await 旨在解決利用非同步結構組織代碼的問題。 為為此增加了兩個新關鍵字:async 和 await。 1.async關鍵字 1.1.使用說明 async 關鍵字用於聲明非同步函數。 函數聲明、函數表達式、箭 ...
好家伙,本篇為《JS高級程式設計》第十章“期約與非同步函數”學習筆記
ES8 的 async/await 旨在解決利用非同步結構組織代碼的問題。
為為此增加了兩個新關鍵字:async 和 await。
1.async關鍵字
1.1.使用說明
async 關鍵字用於聲明非同步函數。
函數聲明、函數表達式、箭頭函數和方法都可以使用
使用 async 關鍵字可以讓函數具有非同步特征,但總體上其代碼仍然是同步求值的。
而在參數或閉包方面,非同步函數仍然具有普通 JavaScript 函數的正常行為。
async function foo() {}
let bar = async function() {};
let baz = async () => {};
class Qux {
async qux() {}
}
1.2.返回值
非同步函數如果使用 return 關鍵字返回了值(如果沒有 return 則會返回 undefined),這個值會被 Promise.resolve()包裝成一個期約對象。
非同步函數始終返回期約對象。
async function foo() {
return 3;
}
console.log(foo());
也可以直接返回一個契約
async function bar() {
console.log("I am bar");
return Promise.resolve(3);
}
console.log("--------------");
console.log(bar());
console.log(1);
1.3.在非同步函數中拋出錯誤會返回拒絕的期約
async function foo() {
console.log(1);
throw 3;
}
// 給返回的期約添加一個拒絕處理程式
foo().catch(console.log);
console.log(2);
1.4.但是,拒絕期約的錯誤不會被非同步函數捕獲
async function foo() {
console.log(1);
Promise.reject(3);
}
// Attach a rejected handler to the returned promise
foo().catch(console.log);
console.log(2);
2.await關鍵字
這裡我們拆分一下 a-wait
也就是asynchronous-wait 非同步-暫停
非同步函數主要針對不會馬上完成的任務,所以自然需要一種暫停和恢復執行的能力。
使用 await 關鍵字可以暫停非同步函數代碼的執行,等待期約解決。
(是暫停非同步)
基本使用
async function foo() {
let p = new Promise((resolve, reject) => setTimeout(resolve, 1000, 3));
console.log(await p);
}
foo();
// 3 (一秒鐘後出現)
(然而這好像看不出什麼)
要完全理解 await 關鍵字,必須知道它並非只是等待一個值可用那麼簡單。
JavaScript 運行時在碰 到 await 關鍵字時,會記錄在哪裡暫停執行。
等到 await 右邊的值可用了,JavaScript 運行時會向消息 隊列中推送一個任務,這個任務會恢復非同步函數的執行。
async function foo(){
console.log(1);
console.log( await 4);
}
foo();
console.log(2);
console.log(3);
這裡我們按上面的話嘗試翻譯一下發生了什麼事
(1)調用非同步函數foo()
(2)輸出1
(3)準備列印,一看誒有個await,先暫停,為立即可用的值4向消息隊列中添加一個任務,
( 怎麼說呢,我反覆看了很多遍.這裡的意思大概是把一個要求值或者說要返回結果的式子推進消息隊列,
但這裡就只有一個4,求個毛線,直接就是4,就是把這個4推進消息隊列. ),後讓出線程
(4)執行同步函數輸出 2
(5)輸出3
(6)"4"求出來了,就是4
(7)await右邊出值了,向消息隊列中添加一個"恢復foo()執行"的任務
(8)從消息隊列中取出"恢復foo()執行"的任務,恢復foo()非同步函數的執行
(9)輸出4
大概就是這麼個過程
3.課後習題
1.請給出下列代碼的輸出結果,並配合"消息隊列"寫出相關解釋
async function foo() { console.log(2); console.log(await Promise.resolve(8)); console.log(9); } async function bar() { console.log(4); console.log(await 6); console.log(7); } console.log(1); foo(); console.log(3); bar(); console.log(5);
嘗試做一下吧,結果一定出乎你的意料
(明天再出一章寫解釋)