异步,回调1

88 阅读3分钟

一、 什么是异步、同步

  1. 如果不能直接拿到结果就是异步
  2. 举例:饭店吃饭等号,拿到号可以先离开,那我们如何知道什么时间可以吃饭?
    • 每十分钟回来问一次前台(轮询)
    • 微信扫码,等轮到的时候接收通知
  3. 如果能拿到结果就是同步
  4. 举例:医院挂号,拿到号才走开进行下一步

二、异步举例

  1. 以AJAX(XMLHttpRequest)举例,
    • r.send()以后并不能直接得到response
    • 必须等到readyState变成4以后,浏览器调用r.onreadystatechange()函数
    • 然后得到response
  2. 这个写给浏览器的函数(onreadystatechange)叫回调(callback)
    • 回调是我写给别人用的,自己并不调用

三、回调举例

  1. 我写给别人用的函数叫回调
  2. 代码:
    function f1(){}
    function f2(fn){  fn()  }
    f2(f1)
    
    • 我是否调用f1? ----否
    • 我把f1传给其他人了么? ---是
    • f2是否调用f1? ---是
    • f1是我写给f2的函数 ----f1是回调

四、异步和回调的关系

  1. 关联:异步任务在需要结果的时候通知JS来拿结果
  2. 如何通知:
    • 让JS留一个函数地址(电话号码)给浏览器
    • 异步任务完成时浏览器调用该地址函数(打电话)
    • 同时把结果作为参数传给该函数(电话里说可以吃饭了)
    • 这个函数时我写给浏览器的,所以是回调函数
  3. 区别
    • 异步任务需用回调函数来通知结果(也可用轮询)
    • 回调任务不一定只在异步任务中
    • 回调也可以在同步任务中(eg.arr.forEach(n=>console.log(n))

五、如何判断是同步还是异步?

当一个函数的返回值处于:①setTimeout() , ② AJAX(即XMLHttpRequest) , ③ AddEventListener等其他API的内部,即为异步函数

六、异步举例

  1. function 摇骰子(){
        setTimeout(()=>{
            return parseInt(Math.random()*6+1)//返回0-6的整数
        },1000)
        //return undefined
    }
    
    • 上述代码中只有setTimeout内的箭头函数有return
    • 函数摇骰子()没有返回值,所以返回return undefined
    • 所以这是一个异步任务
  2. 如果想拿到结果,可以用回调,写个函数然后把函数地址给摇骰子()这个函数
     function 摇骰子(fn){
         setTimeout(()=>{
             fn(parseInt(Math.random()*6+1))},1000)
     }   
     function f1(x){console.log(x)}
     摇骰子(f1)
    
  3. 简写:
    function 摇骰子(){...}
    摇骰子(x=>{console.log(x)})
        //因为这里只有一个参数x,可以继续简写
    摇骰子(console.log)
    


上述简写(摇骰子(console.log)),因为只有一个参数x,所以可简写;当参数不止一个时简写会有问题,

举例

  1. 下面代码期待结果为[1,2,3]
const array1 = ['1','2','3'].map(parseInt)
console.log(array1)

image.png

实际结果

2. 问题在于parseInt接收的参数不止一个,但是写的时候简写所以导致出错
  1. 上述代码等同于:
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
  1. 正确代码为:

image.png