---
tags: JS 直播班 - 2023 秋季班
---
>若有任何疑問請至 Discord「作業討論」頻道討論
# 回呼與非同步操作
本章節將會考驗同學的非同步程式撰寫技巧,以及開始抓取外部的資料,實行 AJAX 技術。
:::warning
**處理非同步上:**
不管是使用 [回呼函式](https://developer.mozilla.org/zh-TW/docs/Glossary/Callback_function)、[promise](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise) 還是 [async](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Statements/async_function)/[await](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/await) 都是可行的。
**處理獲取遠端資料上:**
使用 [fetch](https://developer.mozilla.org/zh-TW/docs/Web/API/Fetch_API/Using_Fetch) 語法或較為早期的 [XMLHttpRequest](https://developer.mozilla.org/zh-TW/docs/Web/API/XMLHttpRequest) 語法或 [Axios](https://axios-http.com/) 函式庫來完成本次作業都是可行的。
**同學可以選擇自身偏好的方式完成目標。**
:::
:::info
下一週將會集中所學,考驗同學串接第三方 API 的能力。可以開始先思考自己有興趣的主題,準備以自己有興趣的 API 來開發一個應用。
* [PUBLIC APIS]( https://publicapis.dev/)
* [政府資料開放平台](https://data.gov.tw/)
:::
:::success
此外可以參考看看助教出題的筆記與其他文章,複習一下非同步 JavaScript 是如何運作的😎
* Webdong - [從動圖輕鬆入門非同步 JavaScript](https://www.webdong.dev/post/async-javascript-visualized-with-ease/)
* Webdong - [非同步 JavaScript 時間操縱之術: setTimeout 與 setInterval](https://www.webdong.dev/post/settimeout-and-setinterval-in-async-javascript/)
* Casper Blog - [JavaScript Promise 全介紹](https://www.casper.tw/development/2020/02/16/all-new-promise/)
* Casper Blog - [Async function / Await 深度介紹](https://www.casper.tw/development/2020/10/16/async-await/)
* web.dev - [JavaScript Promises:簡介](https://web.dev/i18n/zh/promises/)
:::
## 第一題:奇偶數過濾器
請分別製作過濾奇數與偶數的函式做為回呼函式,傳入 filter 函式中,過濾出不同的結果。
```javascript
// Todo 待編輯
const randomNumbers = [1, 8, 10, 22, 137, 31];
function isOdd() {
}
function isEven() {
}
function filter() {
}
console.log(filter(randomNumbers, isOdd))
console.log(filter(randomNumbers, isEven))
// Output 輸出
[1, 137, 31]
[8, 10, 22]
```
## 第二題:定時器
請製作兩個打印文字定時器,分別運用 ```setTimeout``` 與 ```setInterval``` 來達成,間隔一秒打印一次。
```javascript
// Todo 待編輯
function timeoutCounter(start, end) {
}
function intervalCounter(start, end) {
}
timeoutCounter(0, 5)
intervalCounter(0, 5)
// Output 輸出(兩者相同)
0
1
2
3
4
5
```
## 第三題:輸入止抖(debounce)
有個介面當用戶輸入時就會馬上抓取輸入的內容並打出請求到後端去比對(像是圖書館查詢系統),小明輸入了 "Programming Language Javascript" ,但只要每打一個字就送出請求終將會導致發出 "31" 次請求!這無疑是對前端與後端效能影響非常大的一件事!
請製作一個函式,當用戶**停止輸入達到一定時間時,才核實這筆輸入**。
:::spoiler HTML
```htmlembedded
<input placeholder="請輸入內容測試提交狀況">
<ul>
<li>Default:<spant></span></li>
<li>Debounce:<span></span></li>
<li>Throttle:<span></span></li>
</ul>
```
:::
:::spoiler 助教解題文章
[從動圖輕鬆解題:防抖與節流](https://www.webdong.dev/post/learn-debounce-and-throttle/)
:::
<img loading="lazy" src="https://i.imgur.com/XerNeVf.gif">
## 第四題:輸入節流(throttle)
超級英雄使出技能後會有冷卻時間,不可能剛使出很厲害一招的還能一直繼續用,這樣壞人就玩完了,可能每變身完一次就要等 10 分鐘,在這 10 分鐘內英雄再怎麼想要變身都沒有效果。
在寫程式時也常常希望將這樣的特性添加到用戶的輸入中,用戶的輸入是瘋狂的,**需要一個方法讓傳入的函式可以像是有冷卻時間一樣,在輸入冷卻時間完成後才核實這筆輸入**。
請製作一個函式,可以節流用戶的輸入。
:::spoiler HTML
```htmlembedded
<input placeholder="請輸入內容測試提交狀況">
<ul>
<li>Default:<span></span></li>
<li>Debounce:<span></span></li>
<li>Throttle:<span></span></li>
</ul>
```
:::
:::spoiler 助教解題文章
[從動圖輕鬆解題:防抖與節流](https://www.webdong.dev/post/learn-debounce-and-throttle/)
:::
## 第五題:非同步計算矩形面積
請製作一個計算矩形面積的函式。當被呼叫時經過 ```1秒``` 後,使用邊長計算出矩形的面積,使用 console.log 印出。
``` javascript
// Todo 待編輯
function calcRectangleArea(side, callback) {
}
calcRectangleArea(2, () => {
})
// Output 輸出(一秒後)
4
```
## 第六題:非同步錯誤處理
延續上一個題目,撰寫錯誤處理捕捉以下例外情境:
* 輸入非數字
* 輸入非正數
``` javascript
// Todo 待編輯
function calcRectangleArea(side, callback) {
}
calcRectangleArea(2, (error, result) => {
})
// Output 輸出(一秒後)
4
Error: 請輸入正數
TypeError: 請輸入數字
```
## 第七題:改寫至 Promise
延續第五題。改為使用 Promise 來撰寫,成功或失敗都將結果或錯誤使用 console.log 印出。
```javascript
// Todo 待編輯
function calcRectangleArea(side) {
}
calcRectangleArea(2)
Error: 請輸入正數
TypeError: 請輸入數字
```
## 第八題:改寫至 Async / Await
延續第五題。改為使用 Async / Await 來撰寫,成功或失敗都將結果或錯誤使用 console.log 印出。
```javascript
// Todo 待編輯
function calcRectangleArea(side) {
}
calcRectangleArea(2)
Error: 請輸入正數
TypeError: 請輸入數字
```
## 第九題:獲取圖片
製作一個按鈕,點擊時會從伺服器抓取一張圖片顯示到 ```gallery``` 中。
:::spoiler HTML
```html
<button>新增一張圖</button>
<div class="gallery"></div>
```
:::
:::info
假圖可使用 [Lorem Picsum](https://picsum.photos/) ,或是同學自備的外部圖片資源也 OK!
:::
## 第十題:獲取多張圖片
製作一個按鈕,點擊時會從伺服器 **同時** 抓取多張圖片顯示到 ```gallery``` 中。(可使用 [Promise.all](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) 同時處理多個對外請求)
:::spoiler HTML
``` html
<button>獲取五張圖片</button>
<div class="gallery"></div>
```
:::
:::info
假圖可使用 [Lorem Picsum](https://picsum.photos/) ,或是同學自備的外部圖片資源也 OK!
:::
## 回報流程
1. 將答案貼在 Codepen 並複製 Codepen 連結貼至「回報區」回報
(也可以將答案直接貼至「回報區」)
![](https://i.imgur.com/vftL5i0.png)
## 補充
:::info
如遇見相同函式名稱的題目可以善用[區塊](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Statements/block)來分隔彼此的執行階段。
```
const x = 1;
{
const x = 2;
}
console.log(x) // 1
```
:::
## 作業提交等級
* LV1:解出 10 題,並提交 CodePen
* LV2:設計一個 hackmd,嘗試自己設計 10 題
* LV3:嘗試去做其他學生寫的題目,並 tag 學員回報給他,感謝他的命題,讓自己觀念更好
回報區
---
<!-- 參考答案:
https://codepen.io/jmimiding4104/pen/KKJaBBy?editors=1011
答案僅供參考,
答案會使用各種方式書寫(非最佳化)並加上部分解說,
適合初學者還不太會解題或者是該題卡住的同學。
-->
| Discord | LV1 答案 |LV2 自行設計題目 | LV3 做其他學員設計的題目 |
|:-:|:-:|:-:|:-:|
| 銀光菇 | [CodePen](https://codepen.io/genesynthesis/pen/wvNxBXd?editors=1011) | | |
| Chia Pin | [CodePen](https://codepen.io/joker-cat/pen/dyajGro) | | |
| 保羅 | [CodePen](https://codepen.io/paul-1997/pen/OJdwMMy?editors=1011) | | |
| 精靈 | [CodePen](https://codepen.io/justafairy/pen/mdvzEqx) | | |
| Alyce | [CodePen](https://codepen.io/alycehwy/pen/JjxeLjP?editors=0010) | | |
| pinyi_9 | [CodePen](https://codepen.io/Wpypy/pen/YzBROyY?editors=1011) | | |
| bf_tsai | [CodePen](https://codepen.io/BF-Tsai/pen/poGxMpb?editors=1011) | | |
| kuanju27 | [CodePen](https://codepen.io/Eero-Chiao/pen/bGzjVKN) | | |
| runweiting | [CodePen](https://codepen.io/weiting14/pen/mdvYEpY) | | |
| 奔跑吧(GTR150) | [CodePen](https://codepen.io/Wer-Qwe/pen/jOdQOJj?editors=1111) | | |
| 郭芙蘭#6374| [github](https://github.com/Florakuo1112/callback-and-async) | | |
<!--
| xxx | [CodePen](xxx) | | |
-->