觀念解說 – 非同步概念、async await
async 及 await 運用與概念
async 及 await 是執行非同步函式的一種寫法,此寫法可以讓非同步函式在閱讀上更接近同步函式
在非同步函式前加上 async 關鍵字,執行此函式時回傳值就會被轉為一個 Promise
在 async 非同步函式中,使用 await 接收回傳的結果,它會暫停此 async 函式的執行,並且等待 Promise 的解析,解析完之後會回傳解析值,並繼續此 async 函式的執行
也就是說在未等待到結果回傳前,不會執行到 await 之後的程式
1 2 3 4 5 6 7 8 9 10 11 12 13 | function resolveAfter2Seconds(x) { return new Promise(resolve => { setTimeout(() => { resolve(x); }, 2000); }); } async function add1(x) { const a = await resolveAfter2Seconds(20); const b = await resolveAfter2Seconds(30); return x + a + b; } |
參考資源
- Async function / Await 深度介紹 | 卡斯伯 Blog – 前端,沒有極限
- 利用 async 及 await 讓非同步程式設計變得更容易 | MDN
- async、await 再升級(章節影片)
解題
題目(將答案寫在 CodePen 並提交至回報區)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | // 批改作業 function correctTest(name) { return new Promise((resolve, reject) => { setTimeout(() => { const score = Math.round(Math.random()*100); if(score >= 60) { resolve({ name, score }) } else { reject("您已達退學門檻") } }, 2000) }) } // 檢查獎勵 function checkReward(data) { return new Promise((resolve, reject) => { setTimeout(() => { if(data.score >= 90) { resolve(`${data.name} 獲得電影票`); } else if (data.score >= 60 && data.score < 90) { resolve(`${data.name} 獲得嘉獎`); } else { reject(`您沒有獎品`) } }, 2000) }) } |
將以下這段程式碼改寫為 async await 的寫法
1 2 3 4 | correctTest("小明") .then(data => checkReward(data)) .then(reward => console.log(reward)) .catch(error => console.log(error)) |
回覆範例:
1 2 3 4 | const init = async function() { /* 在此填寫答案 */ } init(); |
解答與完整程式碼
解答內容如下。
See the Pen Day 5:非同步概念、async await﹣每日任務﹙Node.js直播班-2022春季班﹚ by Jimmy_Wu (@Jimmy_Wu) on CodePen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | // 批改作業 function correctTest(name) { return new Promise((resolve, reject) => { setTimeout(() => { const score = Math.round(Math.random() * 100); console.log('score', score); if (score >= 60) { resolve({ name, score, }); } else { reject('您已達退學門檻'); } }, 2000); }); } // 檢查獎勵 function checkReward(data) { return new Promise((resolve, reject) => { setTimeout(() => { if (data.score >= 90) { resolve(`${data.name} 獲得電影票`); } else if (data.score >= 60 && data.score < 90) { resolve(`${data.name} 獲得嘉獎`); } else { reject(`您沒有獎品`); } }, 2000); }); } /* 舊 Promise 正確 .then() 與錯誤 .catch() 寫法 ------------------------------------- */ // correctTest('小明') // .then((data) => checkReward(data)) // .then((reward) => console.log(reward)) // .catch((error) => console.log(error)); /* /舊 Promise 正確 .then() 與錯誤 .catch() 寫法 ------------------------------------- */ /* 新 asynce 與 await 寫法 ------------------------------------------------------ */ const init = async function () { /* 在此填寫答案 */ try { let statudenA = await correctTest('小明'); let getReward = await checkReward(statudenA); console.log('getReward', getReward); } catch (error) { console.log('error', error); } }; init(); /* 新 asynce 與 await 寫法 ------------------------------------------------------ */ |