JS同步与异步编程
JS是单线程的, js就是个傻子, 脑子一根筋, 做着当前的这件事情, 没有完成之前绝不会做下一件事情
JS中的两种编程思想
同步
上一件事情没有完成, 继续处理上一件事情, 只有上一件事情完成了, 才会做另一件事情(JS中大部分都是同步编程的)
for(var i = 0; i < 10000; i ++){
if i == 9999(){
console.log("循环结束了~~")
}
console.log("ok")
}
-> 循环结束了~~
-> ok
for循环就是同步编程的, 只有循环结束后, 才会继续执行下面的代码
while(1){
}
console.log("ok")
永远都不会执行 console.log("ok"), 因为上面的循环是死循环, 永远都不会结束
异步
规划要做一件事情, 但是不是当前立马去执行这件事情, 需要等一定的时间, 这样的话, 我们不会等着它执行, 而是继续执行下面的操作, "只有当下面的事情都处理完成了", 只有当下面的事情都处理了, 才会返回头处理之前的事情; 如果下面的事情并没有处理完成, 不管之前的事情有没有到时间, 都踏踏实实的给我等着
实现方法
在JS中异步编程只有四种情况:
- 定时器都是异步编程的
- 所有的事件都是异步编程的
- Ajax读取数据的时候, 我们一般都设置为异步编程
- 回调函数也都是异步编程的
定时器
var n = 0;
window.setTimeout(function(){
n++;
console.log(n);
}, 1000);
console.log(n);
-> 0
-> 1
不立即执行
每一个浏览器对于定时器的等待时间都有一个最小的值, 谷歌:5~6ms IE:10~13ms, 如果设置的等待时间小于这个值, 不起作用, 还是需要等到最小时间才执行; 尤其是写0也不是立即执行.
var n = 0;
window.setTimeout(function(){
n++;
console.log(n);
}, 0);
console.log(n);
-> 0
-> 1
不保证准确的执行时间
我们定时器设置的等待时间不一定就是最终执行的时间, 如果定时器之后还有其他的事情正在处理中, 不管定时器的时间有没有到, 都是不会执行定时器的
var n = 0;
window.setTimeout(function(){
n++;
console.log(n);
}, 0);
console.log(n);
while(1){
n++
}
console.log(n)
-> 0
进入死循环, 浏览器卡死
任务队列
var n = 0;
window.setTimeout(function (){
n += 2;
console.log(n)
}, 2);
window.setTimeout(function (){
n += 5;
console.log(n)
}, 1);
console.log(n);
for(var i =0; i < 10000000; i++){
}
console.log(n);
-> 0
-> 0
-> 5
-> 7
任务队列
任务队列池
任务 -> 2ms执行
将任务->1ms执行添加到队列池中, 发现时间更短的在任务队列中提前排列
任务 -> 1ms执行
任务 -> 2ms执行
执行区
var n = 0;
console.log(n); ->0
执行一千万次的循环, 可能消耗的时间大于20ms也可能小于20ms
console.log(n) -> 0
此时的立即执行的任务都完成了
返回头
开始按照任务池中的任务队列的顺序开始从上到下执行.
事件
for(var i=0; i<oLis.length;i++){
oLis[i].onclick = function(){
console.log(i);
}
}
-> 3
-> 3
-> 3
用户点击的时候, 循环已经执行完了, i已经变成了3.