测理论--异步与回调的关联和区别

简介: 异步与回调的关联和区别

一、异步


如果能直接拿到结果就是同步。

比如:你在医院挂号。任务是拿到号,你只有拿到号,你才会离开

如果不能直接拿到结果就是异步。

比如:网红餐厅排队吃饭,人很多,你的任务是吃饭,只有吃到饭才能离开,那么如果排队人很多,比如给你了一个100号,前面有99人等待,那么你是不是就可以再等待的时候去逛街或者做别的。你可以在这个时间每10分钟去餐厅问一下到你没有(轮询),也可以用手机微信扫码接受通知(回调),知道你吃上饭。

在异AJXA为例,其实request.send()之后,并不能能直接拿到结果,不信可以console.log(request.response)试试,必须等到readyState变成4后,浏览器回头调用request.onreadystatechange函数才可以。


二、回调callback


回调函数是异步操作最基本的方法。简单来说,回调就是自己写了却不调用,给别人调用的函数


代码实例


function f1(){}
function f2(fn){
    fn()
}
f2(f1)


代码1:函数2调用函数1


  1. f1函数被声明,却没有被调用
  2. f1函数当成参数传给f2函数,
  3. f2函数调用了f1函数,所以f1是回调
function f1(x){
    console.log(x)
}
function f2(fn){
    fn('你好')
}
f2(f1)


代码2:


fn('你好')中的fn就是f1, fn('你好')中的你好会被赋值给参数x

那么思考一下最后的结果是打印出你好,你好来自于哪里,是不是f2调用并且给f1传递了一个参数,那么问下f2的运行结果是什么?(参数)


三、异步与回调的关系


关联


异步任务需要在得到结果时通知JS来读取结果。等待通知的过程就是异步,通知JS读取结果的过程就是回调。

具体实现就是让JS编写留下函数地址给浏览器(留下电话号码),异步完成后浏览器调用该函数地址(拨打电话),同时把参数传给该函数(打电话通知顾客取那桌就餐),这个函数是用户写给浏览器调用的,所以是回调函数


区别


异步任务需要用到回调函数来通知结果

回调函数却不一定存在于异步任务中,同步任务中也可以用到回调函数,

例如array.forEach(n=>{console.log(n)}),其中n=>{console.log(n)}就是回调函数


四、如何判断是同步还是异步


异步


如果一个函数的返回值处于如下三种情况就是异步(暂时直说三种)

  • setTimeout
  • AJAX (即XMLHttpRequest)
  • AddEventListener

如果一个函数在这三个内部,就是异步

注意:AJAX也可以设置为同步的,例如在request.open("get", "/style.css", false)添加false。但是在请求期间会让页面卡住,阻止用户其他操作。因此, 异步才是最佳选择。


五、摇骰子例子


例子总结(提前说)

异步任务不能拿到结果,所以需要传一个回调给异步任务。

异步任务完成时调用回调,调用的时候把结果作为参数传给回调函数


第一步


function 摇骰子(){  // 异步函数    
 setTimeout(()=>{     
  return parseInt(Math.random()*6)+1
 },1000)  
 //return undefined 
}  
const n = 摇骰子()
console.log(n) // undefined

摇骰子()没有写return,所以返回return undefined箭头函数返回真正的结果


第二步


function f1(x){console.log(x)} 
function 摇骰子(fn){    
// 异步函数     
setTimeout(()=>{ 
fn(parseInt(Math.random()*6)+1)
 },1000)   
//return undefined 
}  
摇骰子(f1)

怎样拿到异步的结果?

使用回调。

首先声明函数,然后把函数地址传给摇骰子(), 然后摇骰子()得到结果后把结果作为参数传给f1()


第三步(代码简化)


function f1(x){console.log(x)} 
摇骰子(f1)
//简化1
摇骰子( x=>{console.log(x)}) 
 // 简化 2
摇骰子(console.log)//最简

注意,如果参数个数不一致,就不能这样简化到最后一步。函数中一个参数x和一个执行参数x是一致的,简化成功。

例子

// 输入错误结果,简化失败
const array = ['1','2','3']
array.map(parseInt) //  [1, NaN, NaN]
// 正确运行
const array = ['1','2','3']
array.map((item, i, array) =>{
    return parseInt(item)
}


六、回调的弊端


1、在处理回调时代码不够规范,命名不规范

2、容易出现回调地狱

3、很难进行错误处理

目录
相关文章
|
2月前
|
数据库 对象存储
状态机的原理简析及重要用途
状态机的原理简析及重要用途
28 1
|
8月前
|
存储 安全 编译器
大师学SwiftUI第9章Part 2 - 异步并发之Actor、异步序列、任务组和异步图像
异步任务对于希望释放资源让系统可以执行其它任务的场景非常有用,比如更新界面,但在希望同步执行两个任务时,就需要用到并发。为此,Swift标准库定义了async let语句。
34 2
大师学SwiftUI第9章Part 2 - 异步并发之Actor、异步序列、任务组和异步图像
第十二章队列模拟注意事项
第十二章队列模拟注意事项
43 0
|
前端开发
前端学习案例5-执行机制1
前端学习案例5-执行机制1
66 0
前端学习案例5-执行机制1
|
前端开发
前端学习案例6-执行机制2
前端学习案例6-执行机制2
46 0
前端学习案例6-执行机制2
|
JavaScript
浅谈同步、异步、回调函数之间的关系?
同步:发出一个调用时,在没有得到结果之前,该调用就不返回;一旦调用返回,就得到返回值。换句话说,就是由调用者主动等待这个调用的结果。
441 0
|
前端开发
前端工作总结263-判断绑定逻辑
前端工作总结263-判断绑定逻辑
42 0
|
JavaScript 中间件
两分钟搞懂从函数组合到中间件实现
很多JS框架中都会用到中间件,形成一个洋葱圈结构,这样可以很好的应付业务逻辑中的对于切面描述的需要。 经典案例比如Redux 中间件和Koa 中间件
168 1