## 回调函数
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 函数,进行判断是否正确拿到返回结果。
:-: ![](http://xiaoyulive.oss-cn-beijing.aliyuncs.com/date/2018-04-10/1887423177-58086c0c9d5e0_articlex.png)
将上面 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,仍然可以看到异步调用的效果。