1.写在前面
这篇是因为最近再写异步操作,需要点总结
因为还在学习前端的过程中嘛,所以有些东西可能会慢慢补充上来,也可能会有很多个人理解不是很到位的地方,还望各位评论区佬能帮忙指出.阿里嘎多捏
2.异步操作的概念和举例
异步操作和同步操作在408的三门课程中,都有所提及,简单来说,异步操作是一种伪并行,它会将需要事件较长的事件暂时放到队列中,先执行所有的非异步操作.好像一个双线程的东西.
同步操作则是一根筋的处理方式,碰到一个时间较长的执行(比如上传文件)就卡死在这里了,不允许继续做什么.
具体的同步异步,其实和IO控制方式里面的,程序查询方式和程序中断方式很接近.
举个例子
for(var i=1;i<=3;i++){
setIntervel(()=>{
console.log(i);
},1000)
}
猜猜这个执行结果是什么?每隔一秒钟分别输出1 2 3?
戳啦,输出结果是每隔三秒钟输出一个3
原因如下,每次遍历的时候,都有一个定时方法,这个东西会被js引擎当成异步来进行处理
而异步,会被挂到队列,年纪轻轻的引擎,就挂上了三个事件
在此期间,i逐渐自增,最终变成了3,因为变量提升的关系,我们可以在全局读到3,这个时候我们执行完了所有的同步内容,再开始处理队列内容,得到的结果是输出3;
(其他地方不理解记得去了解一下var的变量提升,另外如果想要免去这些操作的影响,可以使用立即执行函数来处理,立即执行函数会把内部的东西统统变成同步)
3.关于异步操作的运行本质
要了解异步操作,首先就要了解js中的事件循环.除了常规的栈区和堆区,js引擎还附带了一个事件队列(event queue),用来临时存放异步操作.
比如说,我们运行了一个操作中,有同步,有异步,顺着往下执行,会先把所有的同步操作给执行完,然后在开始按照队列中的顺序执行异步
每次碰到一个异步操作,就会将其放入事件队列中等待执行.js引擎会通过某些算法来维护这个队列的优先级
目前已知的优先级顺序
1.微操作>宏操作(前者全都执行完了,才轮到后者)
2.同类型的操作,会按照时间排序
4.最简单的异步操作处理机制:回调函数
首先说明:回调函数本身和异步没啥关系,其定义只是把函数当成一个参数传入进去而已
因为这个东西可以起到一个很好的视觉效果和理解能力,所以拿来当作处理异步最通俗的方式
例如,我们用这种方式来进行一个ajax请求
function fetchData(url) {
console.log("调用回调函数1"); //1
var ii=1;
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.send();
console.log("已经发送过send异步方法了2"); //2
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
//因为这个请求铁定是失败的,所以我们不要抱有什么幻想了
}else{
console.log("快,输出点什么证明你还活着!5");
// callback("第"+ ii++ +"次执行回调函数5"); //5
}
}
console.log("先打印这个??3"); //3
}
fetchData('https://api.example.com/data', function(response) {
console.log('请求成功,返回数据为:', response);
});
console.log("这个也是立即执行的东西4"); //4
猜猜这个东西的执行顺序是什么(你也可以自己跑一下)
问题不大,很符合我们之前的预期
这里简单说一下原理,send函数是一个异步操作,当触发send的时候,会把后续的变化挂载到事件队列中(就是触发的readystate的改变,这一大段的内容都会挂载到事件中)
等待同步方法执行完了,队列中就会调出这个东西并且执行
下面是一个个人不太成熟的看法
回调函数其实可有可无,只不过这个形式有助于我们理解队列的挂在
这个回调函数可以把我们想要的内容给直接封装在内罢了