1、异步:
不会卡顿在异步代码那里直接向下执行代码,等待同步代码执行完成后自动触发异步代码的执行。 (比如ajax、定时器)
console.log(100);
setTimeout(function(){
console.log(200);
},1000);
console.log(300);
输出结果解析:立刻打印出100,然后300,等待一秒后打印200
2、同步:
代码按顺序执行,执行的流程不能跨越,需要等待结果完成后才能继续向下执行代码。(比如信息提示弹框,登录和删除功能)
console.log(100);
alert(200); //一秒后再点击确定
console.log(300);
输出结果解析:立刻打印出100,然后弹出提示框,一秒后点击确定按钮后再打印300
3、前端开启异步任务的场景
- 定时任务:
setTimeout(),setInterval()
- 网络请求:
ajax请求,动态< img />加载
- 事件绑定:
onclick等事件
4、js单线程
js是单线程的,同一个时间只能做一件事,所有任务需要排队,前一个任务结束,才会执行后一个任务。
在执行有同步代码和异步代码的代码块中,会优先把所有的同步代码都执行完,才会去执行异步代码,在同步代码执行完之前,是不会去响应异步代码的。
1. 同步任务和异步任务的优先级
console.log(111);
setTimeout(function(){
console.log(222)
},0);
while(1){
}
运行结果分析: 只直接打印出 111 ,然后代码进入死循环,一直没有执行完同步的循环,所以不会执行异步代码。
2. 异步任务的放入和执行时间
for(var i = 0; i < 4; i++){
setTimeout(function(){
console.log(i)
},1000)
}
//上面的代码改写为下面这种形式更好理解一些
for(var i = 0; i < 4; i++){
fn();
}
function fn(){
setTimeout(function(){
console.log(i)
},1000)
}
运行结果分析:一秒之后输出4个4。
当同步代码for循环体循环完了这时全局变量 i 已经是 4了。
在循环的时候每次碰到异步setTimeout任务,浏览器的timer模块先把异步代码提出来,等到1s后浏览器的timer模块才会把定时器的函数体扔到异步队列中,然后异步队列再等待事件循环(event loop)来执行。执行了那四个函数function(){ console.log(i) },所以就打印出了4个4。
5、异步和单线程
众所周知,js是单线程的,但是我们又经常说js异步,这是为什么呢?为什js是单线程的呢?
JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?
实际上浏览器的渲染过程是多线程的,它不只有js一个线程,它还有GUI渲染线程、事件触发线程、定时触发器线程、异步http请求线程等线程。
js一次只能执行一个任务,当他有许多任务时,由于单线程,所以这些任务只能形成一个任务队列排队一个一个来,当前端的某些任务是非常耗时的,比如网络请求,定时器和事件监听,如果让他们和别的任务一样,都老老实实的排队等待执行的话,执行效率会非常的低,甚至导致页面的假死。所以,浏览器为这些耗时任务开辟了另外的线程,主要包括http请求线程,浏览器定时触发器,浏览器事件触发线程,这些任务是异步的。
所以说js单线程和异步并没有什么关系。