一、 什么是异步、同步
- 如果不能直接拿到结果就是异步
- 举例:饭店吃饭等号,拿到号可以先离开,那我们如何知道什么时间可以吃饭?
- 每十分钟回来问一次前台(轮询)
- 微信扫码,等轮到的时候接收通知
- 如果能拿到结果就是同步
- 举例:医院挂号,拿到号才走开进行下一步
二、异步举例
- 以AJAX(XMLHttpRequest)举例,
r.send()以后并不能直接得到response- 必须等到readyState变成4以后,浏览器调用
r.onreadystatechange()函数 - 然后得到response
- 这个写给浏览器的函数(onreadystatechange)叫回调(callback)
- 回调是我写给别人用的,自己并不调用
三、回调举例
- 我写给别人用的函数叫回调
- 代码:
function f1(){} function f2(fn){ fn() } f2(f1)- 我是否调用f1? ----否
- 我把f1传给其他人了么? ---是
- f2是否调用f1? ---是
- f1是我写给f2的函数 ----f1是回调
四、异步和回调的关系
- 关联:异步任务在需要结果的时候通知JS来拿结果
- 如何通知:
- 让JS留一个函数地址(电话号码)给浏览器
- 异步任务完成时浏览器调用该地址函数(打电话)
- 同时把结果作为参数传给该函数(电话里说可以吃饭了)
- 这个函数时我写给浏览器的,所以是回调函数
- 区别:
- 异步任务需用回调函数来通知结果(也可用轮询)
- 回调任务不一定只在异步任务中
- 回调也可以在同步任务中(eg.
arr.forEach(n=>console.log(n)))
五、如何判断是同步还是异步?
当一个函数的返回值处于:①setTimeout() , ② AJAX(即XMLHttpRequest) , ③ AddEventListener等其他API的内部,即为异步函数
六、异步举例
-
function 摇骰子(){ setTimeout(()=>{ return parseInt(Math.random()*6+1)//返回0-6的整数 },1000) //return undefined }- 上述代码中只有setTimeout内的箭头函数有return
- 函数
摇骰子()没有返回值,所以返回return undefined - 所以这是一个异步任务
- 如果想拿到结果,可以用回调,写个函数然后把函数地址给
摇骰子()这个函数function 摇骰子(fn){ setTimeout(()=>{ fn(parseInt(Math.random()*6+1))},1000) } function f1(x){console.log(x)} 摇骰子(f1) - 简写:
function 摇骰子(){...} 摇骰子(x=>{console.log(x)}) //因为这里只有一个参数x,可以继续简写 摇骰子(console.log)
上述简写(摇骰子(console.log)),因为只有一个参数x,所以可简写;当参数不止一个时简写会有问题,
举例
- 下面代码期待结果为
[1,2,3]
const array1 = ['1','2','3'].map(parseInt)
console.log(array1)
实际结果
2. 问题在于parseInt接收的参数不止一个,但是写的时候简写所以导致出错- 上述代码等同于:
const array1 =['1','2','3'].map((item,i,array)={
parseInt(item,i,array)})
//parseInt('1',0)-->parseInt只接受两个参数,且第二个参数范围:2-36
//parseInt('2',1)-->parse第二个参数范围:2-36,所以是NaN
//parseInt('3',2)-->把'3'转为二进制数字,二进制只有0/1,所以是NaN
- 正确代码为: