JS异步解析
同步和异步
举个🌰,你给餐厅打电话,要查某个消费记录,这时候餐厅去查消费记录,你在电话那头等着,不能做其他事情,只有餐厅查到消费记录告诉你才能做其他事情。这个就是同步。
异步就是这样的:你还是去给餐厅打电话,还是要查某个消费记录,这时候餐厅还是去查消费记录,但是餐厅告诉你,你不用等,我们查到就会立马告诉你的,在我们查到之前你可以去做其他事情了。
单线程
我们肯定需要知道,JS为什么需要异步,异步这玩意有什么用。
众所周知,JS是一门单线程的编程语言,也就是说JS同一时间只能做一件事情。JS之所以是单线程的编程语言,是为了避免DOM渲染冲突。
比如说有两段代码,一个代码是将div
的背景颜色设为红色,另一个代码是将div
的背景颜色设为蓝色,如果这两段代码同时进行,这不就冲突了么。只能同一时间运行一段代码,而不是多段代码。
单线程也意味着会发生上一段代码没有执行完毕,下一段代码就无法执行的情况,也就是阻塞。
为了提高运行效率, 异步便是单线程的解决方案。
同步代码示例
alert('我要查消费记录');
console.log('查到了');
在没有点击 alert 弹出的消息之前,“查到了”这条信息是不会出现在控制台的,只有点击 alert 的确定,才能执行console.log('查到了')
。
由此可见,同步会阻塞代码的执行。
异步代码示例
console.log('我要查询消费记录');
setTimeout(function () {
console.log('我查到了');
}, 1000);
console.log('做其他事情');
先输出我要查询记录
,紧接着输出做其他事情
,1s后输出我查到了
。
异步的好处就是不会阻塞代码的执行, 在输出我查到了
这条信息之前,我是可以做其他事情的。
异步的机制
光是了解异步是什么,好处是啥,我认为这还是不够的。我们还需要了解异步的机制,以应对工作中的各种情况,在了解了异步机制后,碰到异步代码也会有不一样的感受。
先看一段代码再说:
// 主线程
console.log(100);
// 异步队列
setTimeout(function () {
console.log(200);
}, 100);
// 异步队列
setTimeout(function () {
console.log(300);
}, 0);
// 主线程
console.log(400);
// 这段代码输出的结果依次为:100,400,300,200
为什么会输出这样的结果呢?
-
主线程代码先执行。
-
同步代码,同步执行。
-
异步函数先放到异步队列当中去。
-
等同步代码执行完毕,再轮询执行异步队列中的函数。
解释一下这段代码执行过程:
console.log(100)
先执行, 输出100
, console.log(300)
立即放入异步队列中去, 100ms后, console.log(200)
放入异步队列中去。
执行console.log(400)
, 输出400
, 同步代码执行完毕。轮询异步队列中的函数。先输出300
, 再输出200
;
异步的原理
这段受王福鹏老师的启发,做补充。感兴趣的同学,可以去点击上面的连接,查看更详细的异步解析。
$.get('xxx.json', function (data, state) {
console.log(data);
});
这是 jQuery 发起 ajax 请求的一段代码,两个参数,一个 url
和一个 function(data, state)
, 这个function(data, state)
不会立即执行,只有请求的数据拿到了,才会执行。
这里引用王福鹏老师的话: 实现异步的最核心原理,就是将callback作为参数传递给异步执行函数,当有结果返回之后再触发 callback执行
异步的使用场景
-
定时任务: setTimeout, setInterval
-
网络请求: ajax请求, 动态
<img>
加载 -
事件绑定