1 同步
- 如果可以直接拿到结果,那就是同步
- 实例: 在医院挂号,拿到号才会离开窗口,无论等待时间多久,不拿到结果是不会离开的
宏任务与微任务
- 宏任务:setTimeout setInterval Ajax DOM事件
- 微任务:Promise async/await
- 先同步再异步,异步任务需要等待同步任务完毕后再进行
- asyn必须与await搭配出现,否则会报错,同时,第一个await之前的代码会同步执行,之后的会异步执行
- 异步中,先清空微任务再执行下一个宏任务,每次执行完宏任务时,先判断微任务队列是否存在微任务,若存在,先执行清空微任务队列,再执行下一个宏任务
2 异步
2.1 概念
- 不能直接拿到结果,那就是异步
- 实例:在餐厅等餐位时,可以拿到号去逛街
- 可以每10分钟去餐厅问一下(轮询)
- 可以扫码用微信接受通知(回调)
2.2 举例
2.2.1 实例:AJAX
- request.send()之后,并不能直接得到response
- 必须等到readyState变为4后,浏览器回头调用request.onreadystatechange函数
- 我们才可以得到request.response
2.2.2 回调 callback
- 自己写给自己用的函数,不是回调
- 自己写给别人用的函数,就是回调
- 例如request.onreadystatechange就是我写给浏览器调用的函数
2.2.3 代码实例
function f1(){}
function f2(fn){
fn()
}
f2(f1)
分析:
- 我没有调用f1
- 我将f1传给了别人
- f2调用了f1
- 所以f1是我写给f2调用的函数,因此f1是回调
2.3 异步与回调的关系
2.3.1 关联
- 异步任务需要在得到结果时通知JS来拿结果
- 让JS留一个函数地址给浏览器
- 异步任务完成时,浏览器调用该函数地址即可
- 同时把这个结果作为参数传给该函数
- 这个函数是我写给浏览器调用的,所以是回调函数
2.3.2 区别
- 异步任务需要用到回调函数来通知结果
- 但回调函数不一定只用在异步任务里
- 回调也可以用到同步任务里
-
array.forEach(n=>console.log(n))
就是同步回调
2.4 判断同步or异步
- 如果一个函数的返回值处于
(1)setTimeout
(2)AJAX(即XMLHttpRequest)
(3)AddEventListener
这三个东西内部,,那这个函数就是异步函数
2.5 过程
- 异步任务不能拿到结果
- 于是我们传一个回调给异步任务
- 异步任务完成时调用回调
- 调用的时候把结果作为参数
2.6 异步任务有两个结果
- 方法一:回调接受两个参数
fs.readFile('./1.txt',(error,data)=>{
if(error){ console.log('失败'); return }
console.log(data.toString()) // 成功
})
- 方法二: 搞两个回调
ajax('get','/1.json',data=>{ },error=>{ })
// data=>{ }是成功回调 error=>{ }是失败回调
ajax(‘get’,'/1.json',{
success:()=>{}, fail:()=>{}
})
// 接受一个对象,对象有两个key表示成功和失败
缺陷:以上两个方法存在三个不足之处
- 不规范,名称五花八门,有人使用success+error,有人使用success+fail等等
- 容易出现回调地狱,代码变得看不懂
- 很难进行错误处理
3 Promise的用法
3.1 以AJAX为例
// 普通回调写法
ajax('get','/xxx',{
success(response){},
fail:(request, status) => {}
})
// Promise写法
// then 的第一个参数是success,成功则返回需要数据
// then 的第二个参数是fail,失败则将刚才的请求拿回来查找问题
ajax('get','/xxx')
.then((respsonse)=>{},(request)=>{})
- ajax返回了一个含有.then方法的对象
3.2 回调异步函数=>Primoise异步函数
第一步:
return new Promise((resolve,reject)=>{……})
- 任务成功则调用
resolve(result)
- 任务失败则调用
reject(error)
- resolve和reject会再去调用成功和失败函数
第二步:
- 使用.then(success,fail)传入成功和失败函数
3.3 jQuery.ajax
使用方法可以参考jQuery文档
3.3.1 封装优点
- 支持更多形式的参数
- 支持Promise
- 支持的功能很多
注意:但现在更推荐使用axios
3.4 axios
是目前最新的AJAX库,采用了jQuery的封装思路。
3.4.1 示例
axios.get('/5.json')
.then( response =>
console.log(response)
)
3.4.2 aixos高级用法
JSON自动处理
axios如果发现响应的Content-Type是json
就会自动调用JSON.parse
请求拦截器
可以在所有请求里加些东西,比如添加查询参数
响应拦截器
可以在所有响应中添加东西,甚至修改内容
可以生成不同的实例(对象)
不同实例可以设置不同配置,用于复杂场景
axios 使用参考文章:https://juejin.cn/post/6844903569745788941
4 注意
4.1 关于异步
1.如果 JS 不能直接拿到一个函数的结果,可以先去执行别的代码,等结果到了再取结果,这就是异步
2.异步的结果可以通过轮询获取,轮询就是定时去询问结果拿到了没有
3.异步的结果可以通过回调获取,一般来说结果会被作为回调的第一个参数
4.异步的好处是可以把用来等待的时间拿去做别的事情
4.2 关于回调
1.满足某些条件的函数才被称为回调,比如我写一个函数 A,传给另一个函数 B 调用,那么函数 A 就是回调
2.回调可以用于同步任务,不一定非要用于异步任务
3.有的时候回调还可以传给一个对象,如 request.onreadystatechange
,等待浏览器来调用
4.3 关于Promise
1.Promise不是前端发明的,是目前前端解决异步问题的统一方案。
2.window.Promise 是一个全局函数,可以用来构造 Promise 对象
3.使用return new Promise((resolve, reject)=> {})
就可以构造一个Promise对象
4.构造出来的Promise对象含有一个 .then()函数属性
4.3 关于return new Promise((resolve, reject)=>{…})
中的resolve和reject
1.resolve 和 reject 可以改成任何其他名字,不影响使用,但一般就叫这两个名字。
2.任务成功的时候调用resolve,失败的时候调用reject
3.resolve和reject都只接收一个数据,而且this是空,不应该用this
4.resolve和reject并不是 .then(success, fail)里面的success和fail,resolve会去调用 success,reject会去调用fail
4.5 注意Promise不可取消
为了解决取消promise这个问题,axios自己想了个办法就是用CancleToken。
原理就是将请求编号,假设发了10个promise,其中9个不要了。就把id为1~9的promise对应的ajax请求终止。promise还是做,只不过ajax不要了。axios取消的不是promise而是请求。axios.CancleToken
部分资料参考来源:饥人谷