## 回調函數
A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.
回調: 是一個函數被作為一個參數傳遞到另一個函數里,在那個函數執行完后再執行。
說成大白話,就是 B函數被作為參數傳遞到A函數里,在A函數執行完后再執行B。
使用回調函數實現 JS 異步是最基本也是最原始的方法,但是,回調也不一定就是異步,
### 同步回調
```
const func = (name, retFun) => {
console.log('1')
retFun(`Hello ${name}`)
console.log('2')
}
console.log('-1-')
func('xiaoyu', function (arg) {
console.log(arg)
})
console.log('-2-')
```
說出結果
```
-1-
1
Hello xiaoyu
2
-2-
```
### 異步回調
異步回調,多出現在 Ajax 請求 (用于處理收到的請求結果)、定時器等操作 (用于指定時間處理結果)。
如果是一個請求,比如使用 jquery 的 `$.ajax()`,瀏覽器會開啟一個網絡請求線程去請求數據,回調函數 `success` 會等到請求成功后才執行,這時就能感受到明顯的異步調用。
因為js是單線程的,但是有很多情況的執行步驟(ajax請求遠程數據,IO等)是非常耗時的,如果一直單線程的堵塞下去會導致程序的等待時間過長頁面失去響應,影響用戶體驗了。
如何去解決這個問題呢,我們可以這么想。耗時的我們都扔給異步去做,做好了再通知下我們做完了,我們拿到數據繼續往下走。
比如一個原生 Ajax 請求 :
```
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true); // 第三個參數決定是否采用異步的方式
xhr.send(data);
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && xhr.status === 200){
// xxxx
}
}
```
上面是一個代碼,瀏覽器在發起一個ajax請求,會單開一個線程去發起http請求,這樣的話就能把這個耗時的過程單獨去自己跑了,在這個線程的請求過程中,readystate 的值會有個變化的過程,每一次變化就觸發一次onreadystatechange 函數,進行判斷是否正確拿到返回結果。
:-: 
將上面 Ajax 請求進行封裝,即可實現異步回調
```
function fetchRes(url, data, success) {
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.send(data);
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && xhr.status === 200){
success(xhr.responseText)
}
}
}
console.log('-1-')
fetchRes('http://www.my-tp5.com/', '',
data => {
console.log(JSON.parse(data))
}
)
console.log('-2-')
```
輸出
```
-1-
-2-
[{…}, {…}, {…}, {…}] // 這是我個人本地接口返回的數據,僅做測試
```
### 使用系統定時器
即使用系統的 setTimeout()、setInterval() 等計時器
```
console.log('-1-')
setTimeout(() => {
console.log('timmer')
}, 0);
console.log('-2-')
```
即使是延時時間為 0,仍然可以看到異步調用的效果。